[java/javascript教程] 你会用ES6,那倒是用啊!!!

[复制链接]
查看1240 | 回复0 | 2022-4-29 17:32:45 | 显示全部楼层 |阅读模式

登录网站,浏览更多精彩内容

您需要 登录 才可以下载或查看,没有账号?加入我们

×
20220429_112551_043.jpg               I, ]' V' W5 u
不是标题党,这是一位leader在一次代码评审会对小组成员发出的“怒吼”,原因是在代码评审中发现很多地方还是采用ES5的写法,也不是说用ES5写法不行,会有BUG,只是造成代码量增多,可读性变差而已。恰好,这位leader有代码洁癖,面对3~5年经验的成员,还写这种水平的代码,极为不满,不断对代码进行吐槽。不过对于他的吐槽,我感觉还是有很大收获的,故就把leader的吐槽记录下来,分享给掘友们,觉得有收获点个赞,有错误的或者更好的写法,非常欢迎在评论中留言。ps:ES5之后的JS语法统称ES6!!!一、关于取值的吐槽取值在程序中非常常见,比如从对象obj中取值。
  1. const obj = {8 u0 A5 S+ t3 _, _+ Y5 O
  2.     a:1,1 H- W1 i( S- b3 Q3 V
  3.     b:2,& Y5 u3 c/ }% i% Q
  4.     c:3,9 j* S% v6 i) j7 p5 A  P/ o  {$ e
  5.     d:4,' K1 F) e0 B+ ?( q) U2 _
  6.     e:5,( v! ~, X/ J% ?2 @- b
  7. }
复制代码
6 B8 D: y" S: Q7 u
吐槽:2 l% _1 f' S* [" J; b
  1. const a = obj.a;
    7 j5 C5 [/ D: d& C. v
  2. const b = obj.b;5 R( P& G5 \, ~7 y& _
  3. const c = obj.c;
    # d8 v3 z9 f7 u1 W" D5 s
  4. const d = obj.d;3 v# o% k- ~7 R7 y
  5. 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
  1. const f = obj.a + obj.d;1 T4 v0 x7 U: r) G8 y
  2. 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
  1. const {a,b,c,d,e} = obj;
    9 N7 ~, e# U; m% i' g# p( `2 @+ c
  2. const f = a + d;; }6 Q. ]' l6 R
  3. const g = c + e;
复制代码
% Z( y' a7 ?& A
反驳不是不用ES6的解构赋值,而是服务端返回的数据对象中的属性名不是我想要的,这样取值,不是还得重新创建个遍历赋值。吐槽看来你对ES6的解构赋值掌握的还是不够彻底。如果想创建的变量名和对象的属性名不一致,可以这么写:
3 r3 m2 `( f& P/ b& z' h8 _
  1. const {a:a1} = obj;% i0 W- L- \; p) `
  2. console.log(a1);// 1补充ES6的解构赋值虽然好用。但是要注意解构的对象不能为undefined、null。否则会报错,故要给被解构的对象一个默认值。0 o4 Y" [7 s& S9 [) S
  3. 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
  1. const b = [1,5,6];9 T2 t. n2 Q& K$ X9 m; Q% P
  2. const c = a.concat(b);//[1,2,3,1,5,6]
    / `" R1 x' c. s5 s
  3. const obj1 = {" r3 M% ?" b+ o, N, C5 d9 s
  4.   a:1,2 s" h) j1 w( r% A: z+ K7 p" n2 ?
  5. }
    , D! L% y! |5 m9 @1 R1 W
  6. const obj2 = {* ?7 L. A9 |7 ]" ]9 X
  7.   b:1,
    6 g) ^- @; ?0 ^" D5 P
  8. }
    + [; {7 |' h: @/ C( b& g
  9. 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
  10. const b = [1,5,6];( Q+ }; E" V; {2 e) s  s9 i
  11. const c = [...new Set([...a,...b])];//[1,2,3,5,6]
    1 I: a1 b0 e9 e' [3 T) S9 _
  12. const obj1 = {. Q% t6 l. g% v& q5 n5 g
  13.   a:1,4 b! }) N  K7 Y8 |3 G  L
  14. }. @8 L( {2 j) Z# N) m& v- n# \
  15. const obj2 = {9 I/ P7 N  Y9 F- t) k3 a5 D
  16.   b:1,
    , q6 N' B* h- U) }. o
  17. }: N! y) j/ S& d) x/ c
  18. const obj = {...obj1,...obj2};//{a:1,b:1}
复制代码

# R" _- b1 a; T) d三、关于拼接字符串的吐槽( n( m7 {1 }1 r5 ?! j
  1. const name = '小明';  J5 B) d* ]$ |/ V
  2. const score = 59;2 Z: j' B  {9 I8 M0 e9 B
  3. let result = '';8 ?9 x8 a3 ~- g; Q( {, u
  4. if(score > 60){+ M% j7 U. F5 R- r0 P9 L4 V- }: P' i
  5.   result = `${name}的考试成绩及格`; - ^! R. n% R: h0 O) T
  6. }else{* R9 B/ ?. L3 d$ M# b( n
  7.   result = `${name}的考试成绩不及格`;
    9 W2 B$ G( X" x) B6 x0 t  _
  8. }
复制代码

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
  1. const score = 59;+ |4 I5 L( N+ n0 [' O
  2. const result = `${name}${score > 60?'的考试成绩及格':'的考试成绩不及格'}`;
复制代码

& O  J/ w+ A9 w. e四、关于if中判断条件的吐槽if(- E+ a5 ?) P9 r: a- M
  1.     type == 1 ||
    ( g7 N( E' J& j* V" t- L
  2.     type == 2 ||6 C% ]( O) C% U3 a+ D. w
  3.     type == 3 ||$ S& W' @# R. J
  4.     type == 4 ||3 k. }6 L( h0 H( L  m4 o- Z  U
  5. ){. _2 {" H3 {5 |+ y) D1 ^
  6.    //...
    * q+ _. y+ Q* M
  7. }
复制代码

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
  1. if( condition.includes(type) ){
    ! C5 p* u1 G- K6 b
  2.    //..., U: p1 T0 J, y6 R3 S0 B1 L
  3. }
复制代码
( 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
  1. const result = a.filter( ; X" o; o( X3 }( b; K  F3 w
  2.   item =>{! D, ~1 y& k( Q
  3.     return item === 3
    ! v* q8 f" J" B" b0 S* }6 ?# w
  4.   }
    ( ?+ s  w; e) d9 O
  5. )
复制代码
. T/ G3 H- ]. i/ K0 ?  q
吐槽如果是精确搜索不会用ES6中的find吗?性能优化懂么,find方法中找到符合条件的项,就不会继续遍历数组。改进const a = [1,2,3,4,5];
: h2 u8 e3 \& ]# V
  1. const result = a.find( $ }, y8 g8 p: u- S
  2.   item =>{; v7 S- V. t: V
  3.     return item === 3
    0 Q, B8 J4 D) x* [1 H2 }
  4.   }, s1 X5 l4 }& K
  5. )
复制代码

1 ~* R$ p; M, P2 Q, y
& J% e  ^0 b4 K% L- F  X六、关于扁平化数组的吐槽一个部门JSON数据中,属性名是部门id,属性值是个部门成员id数组集合,现在要把有部门的成员id都提取到一个数组集合中。
  I7 T$ E, }+ m
  1. const deps = {
    5 ~, Q' x: [2 c% y. d" H
  2. '采购部':[1,2,3],
    : V. j; x0 ]: [: ]0 {4 C' U
  3. '人事部':[5,8,12],
    % c% z& T8 t% D" f4 {
  4. '行政部':[5,14,79],' ^6 I2 K& d3 U
  5. '运输部':[3,64,105],/ k! x; x9 Y) o! ?  }0 N+ e
  6. }1 }# p" p$ ]& x5 n% z
  7. let member = [];
    0 U* T" p! I3 b- V, F5 _/ ^
  8. for (let item in deps){
    ( R' Z+ G( t8 _" J$ }$ l
  9.     const value = deps[item];1 `7 o6 {0 M1 K0 P$ d
  10.     if(Array.isArray(value)){- J6 I4 N* C3 Y9 g' w
  11.         member = [...member,...value]5 ^/ H$ G# [0 d5 i
  12.     }* E5 J3 [2 {' P6 ^- t
  13. }
    & ?& W/ |1 w3 M& N2 _3 y
  14. 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
  1. const deps = {; ~) o+ J" M8 X. h8 W
  2.     '采购部':[1,2,3],
    6 G8 r$ x& ~- W+ }: L/ J# g& k
  3.     '人事部':[5,8,12],
    : I, R" U% m% A4 ^  l
  4.     '行政部':[5,14,79],
    8 s4 [/ g& a0 J# B8 p- o% X
  5.     '运输部':[3,64,105],' M, Z7 i/ u- H' t
  6. }
    ' O7 j. q% A% A5 d
  7. 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
  1. let index = 1;7 _4 r$ G1 `# v* r/ @1 j/ h
  2. let key = `topic${index}`;+ m' f+ z! J& o2 f1 d7 m; |
  3. obj[key] = '话题内容';吐槽为何要额外创建一个变量。不知道ES6中的对象属性名是可以用表达式吗?改进let obj = {};- w8 g7 n0 }& ?+ Q5 k: X$ o1 `
  4. let index = 1;
    $ S" c8 T/ X, B0 }9 _, f4 t% L( f
  5. 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
  1. const fn1 = () =>{
    * `" }; ]' q! r$ B
  2.   return new Promise((resolve, reject) => {
    - J) e6 Q2 J, @- X6 u# L9 }
  3.     setTimeout(() => {
    " p# c  l- N  y: I! V# ]; D
  4.       resolve(1);  }# j5 _$ ?( o; C8 ]
  5.     }, 300);
    # d- l0 L" ?; b
  6.   });: y2 G4 S4 F  c9 n  @
  7. }
    ' b  z2 W$ v* K# G; g
  8. const fn2 = () =>{3 w6 {3 w' G4 ^: `3 [
  9.   return new Promise((resolve, reject) => {- m! |- n& \9 @6 ^' R- s" t
  10.     setTimeout(() => {
    " O( N- S" }% h, y, N, I
  11.       resolve(2);
    - D0 m/ O: C- h5 D
  12.     }, 600);6 ?5 I# H- k2 h& i" E' V0 z
  13.   });4 {6 ^4 ]' K3 O' \/ x
  14. }+ Q* r# @7 m. t
  15. const fn = () =>{: f) _/ g1 l" e! x
  16.    fn1().then(res1 =>{9 R5 k/ y" Z/ M
  17.       console.log(res1);// 1; \9 L7 y3 x+ U# W+ c$ S9 |
  18.       fn2().then(res2 =>{
    ; f# o6 P$ y- c, ^5 g# |2 o& j; D
  19.         console.log(res2)
    2 C% H' U( o( v! k7 \6 g9 B2 w
  20.       })
    , w0 u" Y4 z$ C: H2 ~) p2 }" @
  21.    })
    . f; f* J2 `* S
  22. }
复制代码

! e8 q0 |9 A6 R1 x2 |吐槽如果这样调用异步函数,不怕形成地狱回调啊!改进
# Y' V6 q( z* r' Y7 j$ i) ~6 A
  1. const fn = async () =>{
    $ e8 G& E* [! V( T- t/ v
  2.   const res1 = await fn1();
    7 F$ X& d! B9 z& _9 a. v
  3.   const res2 = await fn2();
    : p. s- `/ \) V2 F3 l) Y2 \
  4.   console.log(res1);// 1
    . O! e. u$ O' J6 X  M
  5.   console.log(res2);// 2- G1 |! _. a5 ?# y( B
  6. }
复制代码
, Q, D: L6 [* x( h1 u
补充但是要做并发请求时,还是要用到$ {- c. j& y( a% V1 A( u3 ?; Y' O" n
  1. Promise.all()
    - Z8 a' U. [, l& _: \, y) m+ v4 t
  2. const fn = () =>{
    . E& y1 y% I: S# _* v  e
  3.    Promise.all([fn1(),fn2()]).then(res =>{5 u4 M+ _4 \" o' ]9 w% ]
  4.        console.log(res);// [1,2]
    ; X% ^9 K/ Q8 v
  5.    }) % W8 ?1 y2 A  e6 D+ r% v2 A1 S7 H
  6. }
复制代码

, |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
中国领先的数字技术资源交流中心!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

5

主题

4

回帖

199

积分

学徒

积分
199
学费
176