登录网站,浏览更多精彩内容
您需要 登录 才可以下载或查看,没有账号?加入我们
×
I, ]' V' W5 u
不是标题党,这是一位leader在一次代码评审会对小组成员发出的“怒吼”,原因是在代码评审中发现很多地方还是采用ES5的写法,也不是说用ES5写法不行,会有BUG,只是造成代码量增多,可读性变差而已。恰好,这位leader有代码洁癖,面对3~5年经验的成员,还写这种水平的代码,极为不满,不断对代码进行吐槽。不过对于他的吐槽,我感觉还是有很大收获的,故就把leader的吐槽记录下来,分享给掘友们,觉得有收获点个赞,有错误的或者更好的写法,非常欢迎在评论中留言。ps:ES5之后的JS语法统称ES6!!!一、关于取值的吐槽取值在程序中非常常见,比如从对象obj中取值。- const obj = {8 u0 A5 S+ t3 _, _+ Y5 O
- a:1,1 H- W1 i( S- b3 Q3 V
- b:2,& Y5 u3 c/ }% i% Q
- c:3,9 j* S% v6 i) j7 p5 A P/ o {$ e
- d:4,' K1 F) e0 B+ ?( q) U2 _
- e:5,( v! ~, X/ J% ?2 @- b
- }
复制代码 6 B8 D: y" S: Q7 u
吐槽:2 l% _1 f' S* [" J; b
- const a = obj.a;
7 j5 C5 [/ D: d& C. v - const b = obj.b;5 R( P& G5 \, ~7 y& _
- const c = obj.c;
# d8 v3 z9 f7 u1 W" D5 s - const d = obj.d;3 v# o% k- ~7 R7 y
- const e = obj.e;
复制代码
! J2 I/ l7 r# H1 D! `# m1 d, V
6 W$ ^; @2 }9 b- _2 a- ?或者
" c. W: I' c2 P1 R" J- const f = obj.a + obj.d;1 T4 v0 x7 U: r) G8 y
- const g = obj.c + obj.e;
复制代码 9 x* b ~" _0 s. S
吐槽:“不会用ES6的解构赋值来取值吗?5行代码用1行代码搞定不香吗?直接用对象名加属性名去取值,要是对象名短还好,很长呢?搞得代码中到处都是这个对象名.8 H$ Z' @, C" u3 N; S) q `/ X
”改进:
9 [% T$ P. }! L9 x- const {a,b,c,d,e} = obj;
9 N7 ~, e# U; m% i' g# p( `2 @+ c - const f = a + d;; }6 Q. ]' l6 R
- const g = c + e;
复制代码 % Z( y' a7 ?& A
反驳不是不用ES6的解构赋值,而是服务端返回的数据对象中的属性名不是我想要的,这样取值,不是还得重新创建个遍历赋值。吐槽看来你对ES6的解构赋值掌握的还是不够彻底。如果想创建的变量名和对象的属性名不一致,可以这么写:
3 r3 m2 `( f& P/ b& z' h8 _- const {a:a1} = obj;% i0 W- L- \; p) `
- console.log(a1);// 1补充ES6的解构赋值虽然好用。但是要注意解构的对象不能为undefined、null。否则会报错,故要给被解构的对象一个默认值。0 o4 Y" [7 s& S9 [) S
- const {a,b,c,d,e} = obj || {};
复制代码 - _# K. ^8 w* I) [+ a! B% J0 a# w
二、关于合并数据的吐槽比如合并两个数组,合并两个对象。const a = [1,2,3];
$ m/ e( u! }& ]2 y0 Y- const b = [1,5,6];9 T2 t. n2 Q& K$ X9 m; Q% P
- const c = a.concat(b);//[1,2,3,1,5,6]
/ `" R1 x' c. s5 s - const obj1 = {" r3 M% ?" b+ o, N, C5 d9 s
- a:1,2 s" h) j1 w( r% A: z+ K7 p" n2 ?
- }
, D! L% y! |5 m9 @1 R1 W - const obj2 = {* ?7 L. A9 |7 ]" ]9 X
- b:1,
6 g) ^- @; ?0 ^" D5 P - }
+ [; {7 |' h: @/ C( b& g - const obj = Object.assign({}, obj1, obj2);//{a:1,b:1}吐槽ES6的扩展运算符是不是忘记了,还有数组的合并不考虑去重吗?改进const a = [1,2,3];
1 v9 s, m$ {0 Y5 k- m M' d+ L - const b = [1,5,6];( Q+ }; E" V; {2 e) s s9 i
- const c = [...new Set([...a,...b])];//[1,2,3,5,6]
1 I: a1 b0 e9 e' [3 T) S9 _ - const obj1 = {. Q% t6 l. g% v& q5 n5 g
- a:1,4 b! }) N K7 Y8 |3 G L
- }. @8 L( {2 j) Z# N) m& v- n# \
- const obj2 = {9 I/ P7 N Y9 F- t) k3 a5 D
- b:1,
, q6 N' B* h- U) }. o - }: N! y) j/ S& d) x/ c
- const obj = {...obj1,...obj2};//{a:1,b:1}
复制代码
# R" _- b1 a; T) d三、关于拼接字符串的吐槽( n( m7 {1 }1 r5 ?! j
- const name = '小明'; J5 B) d* ]$ |/ V
- const score = 59;2 Z: j' B {9 I8 M0 e9 B
- let result = '';8 ?9 x8 a3 ~- g; Q( {, u
- if(score > 60){+ M% j7 U. F5 R- r0 P9 L4 V- }: P' i
- result = `${name}的考试成绩及格`; - ^! R. n% R: h0 O) T
- }else{* R9 B/ ?. L3 d$ M# b( n
- result = `${name}的考试成绩不及格`;
9 W2 B$ G( X" x) B6 x0 t _ - }
复制代码
4 q+ x$ D1 R. Y: R$ N6 \' t' E5 c! l0 g$ }$ W' k
吐槽像你们这样用ES6字符串模板,还不如不用,你们根本不清楚在${}中可以做什么操作。在${}中可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性。改进const name = '小明';
& e1 W5 {: w- v) Y# u- const score = 59;+ |4 I5 L( N+ n0 [' O
- const result = `${name}${score > 60?'的考试成绩及格':'的考试成绩不及格'}`;
复制代码
& O J/ w+ A9 w. e四、关于if中判断条件的吐槽if(- E+ a5 ?) P9 r: a- M
- type == 1 ||
( g7 N( E' J& j* V" t- L - type == 2 ||6 C% ]( O) C% U3 a+ D. w
- type == 3 ||$ S& W' @# R. J
- type == 4 ||3 k. }6 L( h0 H( L m4 o- Z U
- ){. _2 {" H3 {5 |+ y) D1 ^
- //...
* q+ _. y+ Q* M - }
复制代码
8 e9 H- M n6 f0 y3 a吐槽ES6中数组实例方法includes会不会使用呢?1 a6 [' w G- \6 y3 |0 t/ I
改进const condition = [1,2,3,4];: k4 `- y( z, e2 P
- if( condition.includes(type) ){
! C5 p* u1 G- K6 b - //..., U: p1 T0 J, y6 R3 S0 B1 L
- }
复制代码 ( n; W" [ _ I) F3 j8 k5 _% F# s# D
五、关于列表搜索的吐槽在项目中,一些没分页的列表的搜索功能由前端来实现,搜索一般分为精确搜索和模糊搜索。搜索也要叫过滤,一般用filter来实现。const a = [1,2,3,4,5];
/ _2 R1 A6 O! H1 m! t2 S- const result = a.filter( ; X" o; o( X3 }( b; K F3 w
- item =>{! D, ~1 y& k( Q
- return item === 3
! v* q8 f" J" B" b0 S* }6 ?# w - }
( ?+ s w; e) d9 O - )
复制代码 . T/ G3 H- ]. i/ K0 ? q
吐槽如果是精确搜索不会用ES6中的find吗?性能优化懂么,find方法中找到符合条件的项,就不会继续遍历数组。改进const a = [1,2,3,4,5];
: h2 u8 e3 \& ]# V- const result = a.find( $ }, y8 g8 p: u- S
- item =>{; v7 S- V. t: V
- return item === 3
0 Q, B8 J4 D) x* [1 H2 } - }, s1 X5 l4 }& K
- )
复制代码
1 ~* R$ p; M, P2 Q, y
& J% e ^0 b4 K% L- F X六、关于扁平化数组的吐槽一个部门JSON数据中,属性名是部门id,属性值是个部门成员id数组集合,现在要把有部门的成员id都提取到一个数组集合中。
I7 T$ E, }+ m- const deps = {
5 ~, Q' x: [2 c% y. d" H - '采购部':[1,2,3],
: V. j; x0 ]: [: ]0 {4 C' U - '人事部':[5,8,12],
% c% z& T8 t% D" f4 { - '行政部':[5,14,79],' ^6 I2 K& d3 U
- '运输部':[3,64,105],/ k! x; x9 Y) o! ? }0 N+ e
- }1 }# p" p$ ]& x5 n% z
- let member = [];
0 U* T" p! I3 b- V, F5 _/ ^ - for (let item in deps){
( R' Z+ G( t8 _" J$ }$ l - const value = deps[item];1 `7 o6 {0 M1 K0 P$ d
- if(Array.isArray(value)){- J6 I4 N* C3 Y9 g' w
- member = [...member,...value]5 ^/ H$ G# [0 d5 i
- }* E5 J3 [2 {' P6 ^- t
- }
& ?& W/ |1 w3 M& N2 _3 y - member = [...new Set(member)]
复制代码 + C( k" A. {5 b: k# k8 o
" @+ Z% J: ]$ P9 ~* |
吐槽获取对象的全部属性值还要遍历吗?Object.values忘记了吗?还有涉及到数组的扁平化处理,为啥不用ES6提供的flat方法呢,还好这次的数组的深度最多只到2维,还要是遇到4维、5维深度的数组,是不是得循环嵌套循环来扁平化?
0 Z. L3 B7 ]! m8 L! I改进
* ^" F" ^7 ^" S" Z1 Z6 v3 l8 Z- const deps = {; ~) o+ J" M8 X. h8 W
- '采购部':[1,2,3],
6 G8 r$ x& ~- W+ }: L/ J# g& k - '人事部':[5,8,12],
: I, R" U% m% A4 ^ l - '行政部':[5,14,79],
8 s4 [/ g& a0 J# B8 p- o% X - '运输部':[3,64,105],' M, Z7 i/ u- H' t
- }
' O7 j. q% A% A5 d - let member = Object.values(deps).flat(Infinity);
复制代码
9 C+ s$ ~+ ^) F; i+ V其中使用Infinity作为flat的参数,使得无需知道被扁平化的数组的维度。补充flat方法不支持IE浏览器。七、关于获取对象属性值的吐槽const name = obj && obj.name;吐槽ES6中的可选链操作符会使用么?改进const name = obj?.name;八、关于添加对象属性的吐槽当给对象添加属性时,如果属性名是动态变化的,该怎么处理。let obj = {};2 a H q; i' k6 L% W; k
- let index = 1;7 _4 r$ G1 `# v* r/ @1 j/ h
- let key = `topic${index}`;+ m' f+ z! J& o2 f1 d7 m; |
- obj[key] = '话题内容';吐槽为何要额外创建一个变量。不知道ES6中的对象属性名是可以用表达式吗?改进let obj = {};- w8 g7 n0 }& ?+ Q5 k: X$ o1 `
- let index = 1;
$ S" c8 T/ X, B0 }9 _, f4 t% L( f - obj[`topic${index}`] = '话题内容';
复制代码
' P/ S d/ j$ E: R k" T( k- M0 G b/ Q6 h5 }9 u: r4 v. W
九、关于输入框非空的判断在处理输入框相关业务时,往往会判断输入框未输入值的场景。if(value !== null && value !== undefined && value !== ''){
" q' ~: W6 t; r: g //...( i" s8 ]+ N0 M
}
4 |4 N+ q0 x$ s1 M吐槽ES6中新出的空值合并运算符了解过吗,要写那么多条件吗?" G# ]- R; K0 N" U0 \
if((value??'') !== ''){& y' a# S9 Q; R- e- \
//...; \$ v8 X# ], N) {
}
9 l+ @5 H7 D2 O1 p+ I十、关于异步函数的吐槽异步函数很常见,经常是用 Promise 来实现。$ l/ A! v$ U# _; s3 s0 Z, N
- const fn1 = () =>{
* `" }; ]' q! r$ B - return new Promise((resolve, reject) => {
- J) e6 Q2 J, @- X6 u# L9 } - setTimeout(() => {
" p# c l- N y: I! V# ]; D - resolve(1); }# j5 _$ ?( o; C8 ]
- }, 300);
# d- l0 L" ?; b - });: y2 G4 S4 F c9 n @
- }
' b z2 W$ v* K# G; g - const fn2 = () =>{3 w6 {3 w' G4 ^: `3 [
- return new Promise((resolve, reject) => {- m! |- n& \9 @6 ^' R- s" t
- setTimeout(() => {
" O( N- S" }% h, y, N, I - resolve(2);
- D0 m/ O: C- h5 D - }, 600);6 ?5 I# H- k2 h& i" E' V0 z
- });4 {6 ^4 ]' K3 O' \/ x
- }+ Q* r# @7 m. t
- const fn = () =>{: f) _/ g1 l" e! x
- fn1().then(res1 =>{9 R5 k/ y" Z/ M
- console.log(res1);// 1; \9 L7 y3 x+ U# W+ c$ S9 |
- fn2().then(res2 =>{
; f# o6 P$ y- c, ^5 g# |2 o& j; D - console.log(res2)
2 C% H' U( o( v! k7 \6 g9 B2 w - })
, w0 u" Y4 z$ C: H2 ~) p2 }" @ - })
. f; f* J2 `* S - }
复制代码
! e8 q0 |9 A6 R1 x2 |吐槽如果这样调用异步函数,不怕形成地狱回调啊!改进
# Y' V6 q( z* r' Y7 j$ i) ~6 A- const fn = async () =>{
$ e8 G& E* [! V( T- t/ v - const res1 = await fn1();
7 F$ X& d! B9 z& _9 a. v - const res2 = await fn2();
: p. s- `/ \) V2 F3 l) Y2 \ - console.log(res1);// 1
. O! e. u$ O' J6 X M - console.log(res2);// 2- G1 |! _. a5 ?# y( B
- }
复制代码 , Q, D: L6 [* x( h1 u
补充但是要做并发请求时,还是要用到$ {- c. j& y( a% V1 A( u3 ?; Y' O" n
- Promise.all()
- Z8 a' U. [, l& _: \, y) m+ v4 t - const fn = () =>{
. E& y1 y% I: S# _* v e - Promise.all([fn1(),fn2()]).then(res =>{5 u4 M+ _4 \" o' ]9 w% ]
- console.log(res);// [1,2]
; X% ^9 K/ Q8 v - }) % W8 ?1 y2 A e6 D+ r% v2 A1 S7 H
- }
复制代码
, |0 b) x" f4 K如果并发请求时,只要其中一个异步函数处理完成,就返回结果,要用到Promise.race()。: M1 p/ S- A5 l0 F7 D
十一、后续欢迎来对以上十点leader的吐槽进行反驳,你的反驳如果有道理的,下次代码评审会上,我替你反驳。此外以上的整理内容有误的地方,欢迎在原文评论中指正,万分感谢。5 T/ A" G$ w4 {' s, ?; l
* Y0 q2 B) ]5 ~ P w* H! S) P/ p
/ |/ ^2 v8 C* {7 I$ R9 v |
|