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

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

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

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

×
20220429_112551_043.jpg             
$ [) ^; G- ]: f2 e6 k0 u不是标题党,这是一位leader在一次代码评审会对小组成员发出的“怒吼”,原因是在代码评审中发现很多地方还是采用ES5的写法,也不是说用ES5写法不行,会有BUG,只是造成代码量增多,可读性变差而已。恰好,这位leader有代码洁癖,面对3~5年经验的成员,还写这种水平的代码,极为不满,不断对代码进行吐槽。不过对于他的吐槽,我感觉还是有很大收获的,故就把leader的吐槽记录下来,分享给掘友们,觉得有收获点个赞,有错误的或者更好的写法,非常欢迎在评论中留言。ps:ES5之后的JS语法统称ES6!!!一、关于取值的吐槽取值在程序中非常常见,比如从对象obj中取值。
  1. const obj = {
    5 C) d$ i5 \! S) m( _# i+ ]
  2.     a:1,( \- S$ K2 c( p4 K9 [- _
  3.     b:2,( F8 D5 O6 {- g! k# N4 L1 D
  4.     c:3,
    ! b: i( L# ^7 {: F: K3 ]
  5.     d:4,
    * Q' e! n. N' V  q& e
  6.     e:5,
    2 @: a/ M1 A8 j# s% |& S! m: J
  7. }
复制代码

$ a  b5 e" }( x( [! v1 M3 g; C8 a9 Y吐槽:8 D0 M, t1 U# \6 `# D: d$ v
  1. const a = obj.a;
    $ j( b  ]: J5 i3 `+ t. B
  2. const b = obj.b;: B" a6 ?6 O9 R+ c3 i
  3. const c = obj.c;: {6 C$ E) |5 t) Y8 @% _, K5 {+ M
  4. const d = obj.d;  n0 k& W% \/ q, E  @
  5. const e = obj.e;
复制代码
% o. z& ?( \2 x

2 |7 Z# h/ Y. @) ^( c/ }' ~+ h或者. f: s& n# T1 D( K2 {
  1. const f = obj.a + obj.d;
    ! n% g; f: h0 `" V( U+ h
  2. const g = obj.c + obj.e;
复制代码

4 w# d3 W' i- Y$ g) s" u* Q: H吐槽:“不会用ES6的解构赋值来取值吗?5行代码用1行代码搞定不香吗?直接用对象名加属性名去取值,要是对象名短还好,很长呢?搞得代码中到处都是这个对象名.
! {; p1 D5 Y9 F2 {5 G7 Z7 c”改进:* W2 ^( J& w6 Q2 t3 U: R
  1. const {a,b,c,d,e} = obj;1 ]! `5 `- ?/ T) |
  2. const f = a + d;
    5 {) D9 y# o2 s9 o& o8 {& Q
  3. const g = c + e;
复制代码
' R/ _" u3 e- j1 F$ H9 A% r: p
反驳不是不用ES6的解构赋值,而是服务端返回的数据对象中的属性名不是我想要的,这样取值,不是还得重新创建个遍历赋值。吐槽看来你对ES6的解构赋值掌握的还是不够彻底。如果想创建的变量名和对象的属性名不一致,可以这么写:  V6 H7 O) E; Z
  1. const {a:a1} = obj;
    . a) d$ v- f( G3 {, q
  2. console.log(a1);// 1补充ES6的解构赋值虽然好用。但是要注意解构的对象不能为undefined、null。否则会报错,故要给被解构的对象一个默认值。
    - ^- ~( {6 Y, S3 F1 n6 Y
  3. const {a,b,c,d,e} = obj || {};
复制代码
' O" _2 j' W7 |1 z6 O8 ~. g
二、关于合并数据的吐槽比如合并两个数组,合并两个对象。const a = [1,2,3];
4 u. O+ ^; t$ Q& K
  1. const b = [1,5,6];
    6 _8 h4 ]% `) J7 [- [# P# U
  2. const c = a.concat(b);//[1,2,3,1,5,6]4 k  |6 y( _6 ]% u1 ^. b5 g
  3. const obj1 = {  c$ D  P0 o0 F4 R7 T& s+ k
  4.   a:1,( h. L, J; Q, d- E: N
  5. }
    1 x& h. Y( W+ ^+ O. b! J2 s
  6. const obj2 = {
    # U- c9 j# g* h
  7.   b:1," }/ [) X; |3 B/ |" w7 L0 \
  8. }/ [' V0 W6 h1 {1 l* E  o, N+ m
  9. const obj = Object.assign({}, obj1, obj2);//{a:1,b:1}吐槽ES6的扩展运算符是不是忘记了,还有数组的合并不考虑去重吗?改进const a = [1,2,3];
    ; B2 E1 `( ]: H' b: }
  10. const b = [1,5,6];% {2 }+ r2 C0 h/ }4 S. Q* Z
  11. const c = [...new Set([...a,...b])];//[1,2,3,5,6]/ b. X9 N7 {* z
  12. const obj1 = {
    5 \, `1 v6 }$ {7 q2 k) D8 Y
  13.   a:1,
      c) {2 r" z' }
  14. }7 V. L( w1 _( C9 f/ ]8 o
  15. const obj2 = {# h5 f2 h# G5 B) `
  16.   b:1,
    8 c2 f, a5 }% @- Z
  17. }
    0 I# K' }- ?+ i% G  \
  18. const obj = {...obj1,...obj2};//{a:1,b:1}
复制代码

/ V) W9 V) e$ s三、关于拼接字符串的吐槽- q' Y# i/ d8 e  \1 H
  1. const name = '小明';* K& p( f: l% f: I: u. C1 ~* o5 J
  2. const score = 59;8 |! O$ ~2 G) Q# C( G+ A8 l
  3. let result = '';. K1 u/ v! ?* \# P# ~( x* B& k: D
  4. if(score > 60){3 a/ k8 a( |5 K1 H
  5.   result = `${name}的考试成绩及格`;
    " ~( j6 X* [% v, L5 B5 }; [
  6. }else{+ P( u" _1 g/ T; i5 g% Q0 F2 D1 _
  7.   result = `${name}的考试成绩不及格`;
    7 E' g5 Z% i# h' m2 B
  8. }
复制代码

2 R7 P' o  v4 H0 F1 T; K# S5 v7 I8 W- |% x! R8 x
吐槽像你们这样用ES6字符串模板,还不如不用,你们根本不清楚在${}中可以做什么操作。在${}中可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性。改进const name = '小明';& B2 Y+ S$ D% r  n
  1. const score = 59;
    4 C" {. E& X& l% A2 X. F
  2. const result = `${name}${score > 60?'的考试成绩及格':'的考试成绩不及格'}`;
复制代码
  k* L3 S- p5 K" |6 h
四、关于if中判断条件的吐槽if(
3 N/ }: f4 k. w
  1.     type == 1 ||0 a! ?: T/ c6 C8 }2 ?
  2.     type == 2 ||2 s' V- d2 g* T' r3 T5 L
  3.     type == 3 ||
      U; S  M6 r. V' D; ^) ?6 _
  4.     type == 4 ||
    3 l1 g/ |' U& z3 e: b
  5. ){  E" a$ k3 K$ p6 i! k* @
  6.    //...
    ' K9 X9 O" p, z: C0 p. [
  7. }
复制代码

( b2 T+ m/ D1 m) r1 [, G5 j& E吐槽ES6中数组实例方法includes会不会使用呢?
% B6 v; l  D2 X: F改进const condition = [1,2,3,4];4 l! j+ G- j' j. S
  1. if( condition.includes(type) ){
    ; l+ l7 i1 \: X# s( }1 O
  2.    //...
    1 T, s7 F5 U3 j1 G: X: P
  3. }
复制代码

) V7 E9 P( o. c4 j五、关于列表搜索的吐槽在项目中,一些没分页的列表的搜索功能由前端来实现,搜索一般分为精确搜索和模糊搜索。搜索也要叫过滤,一般用filter来实现。const a = [1,2,3,4,5];
* ]) q% ?: Y. h# `- }" g* P3 V
  1. const result = a.filter( # \% A2 a( n) y8 H) ]: Y6 m
  2.   item =>{
    ; O1 c2 I$ ?7 o- X
  3.     return item === 3/ }! z/ c6 y/ C, b! {7 X5 {
  4.   }$ G0 X( ^- N2 S5 z* X) \
  5. )
复制代码

$ n& h* u6 z9 O) t吐槽如果是精确搜索不会用ES6中的find吗?性能优化懂么,find方法中找到符合条件的项,就不会继续遍历数组。改进const a = [1,2,3,4,5];
& H% G2 l4 p8 Q$ x
  1. const result = a.find( 5 Y& K# K) ^2 x' k/ q3 e8 I
  2.   item =>{
    + w) N: Q2 B2 j& |( M7 C0 f2 `9 w
  3.     return item === 3
    - K) A8 u7 `4 _9 {/ C# L
  4.   }  B- S! v' U( m, d% a3 d6 ?
  5. )
复制代码
; u' {& K/ j5 l+ ~" X* U& S4 x
% Y. F. d2 R/ R6 X8 g$ S  Q7 B
六、关于扁平化数组的吐槽一个部门JSON数据中,属性名是部门id,属性值是个部门成员id数组集合,现在要把有部门的成员id都提取到一个数组集合中。' Y  ^8 t6 y8 X) O
  1. const deps = {7 f$ x% p- q* w8 J4 T! A  m9 n9 ~
  2. '采购部':[1,2,3],
    0 Q/ T5 [4 `- N" v$ S) S- H
  3. '人事部':[5,8,12],8 k3 ]9 G0 Y( ^) i
  4. '行政部':[5,14,79],% w- {& b- Q; U5 {5 w
  5. '运输部':[3,64,105],
    + S+ ]1 I' a% x! q" p" L! e
  6. }+ b9 x$ W! N" r  x6 n4 L5 ]* `
  7. let member = [];
    0 T1 O) T; n  B/ W
  8. for (let item in deps){
    4 H5 T4 ^2 M, U# P0 ^! m* ^
  9.     const value = deps[item];; P6 Q5 O; r5 s- ]4 H9 M- [
  10.     if(Array.isArray(value)){
    * ~" W6 e) I2 B
  11.         member = [...member,...value]
    " ^* T( v. }, U( N" y+ [
  12.     }
    8 _, j8 x( s4 ?" J* U2 I
  13. }) j8 D! P4 \' t# Y
  14. member = [...new Set(member)]
复制代码
& B4 T* T& p. S% F2 h0 d) C
5 t  v& ~# G% c
吐槽获取对象的全部属性值还要遍历吗?Object.values忘记了吗?还有涉及到数组的扁平化处理,为啥不用ES6提供的flat方法呢,还好这次的数组的深度最多只到2维,还要是遇到4维、5维深度的数组,是不是得循环嵌套循环来扁平化?
: q/ i: o  ^5 t, k; e改进% H( K4 C) n5 ]7 T
  1. const deps = {
    ' R) A' h8 |, s! g2 D
  2.     '采购部':[1,2,3],/ |) O& P8 S; s& T9 _# C- i# k
  3.     '人事部':[5,8,12],
    . h* [" f  w6 N7 K  _8 o3 s) z5 B5 g/ t
  4.     '行政部':[5,14,79],
    ! G3 w5 Q' k  C0 r( g
  5.     '运输部':[3,64,105],3 o2 g7 ~; l- ]' `$ I9 H
  6. }: l" C# @2 D/ o/ @
  7. let member = Object.values(deps).flat(Infinity);
复制代码

* K0 Z: T9 B4 i  A( S/ P其中使用Infinity作为flat的参数,使得无需知道被扁平化的数组的维度。补充flat方法不支持IE浏览器。七、关于获取对象属性值的吐槽const name = obj && obj.name;吐槽ES6中的可选链操作符会使用么?改进const name = obj?.name;八、关于添加对象属性的吐槽当给对象添加属性时,如果属性名是动态变化的,该怎么处理。let obj = {};
7 i# G3 H# [1 d! ~7 n/ w9 W
  1. let index = 1;
    6 w( |# {8 j5 c/ W! u- y
  2. let key = `topic${index}`;, {4 n7 H' [. G+ U1 ~
  3. obj[key] = '话题内容';吐槽为何要额外创建一个变量。不知道ES6中的对象属性名是可以用表达式吗?改进let obj = {};2 u8 {; [: X, v. x. @- s3 K
  4. let index = 1;
    1 y# F7 I5 |- G0 [" R; r5 P
  5. obj[`topic${index}`] = '话题内容';
复制代码

5 J9 }! e4 w- ?+ f! i+ v
: a, l# K9 G/ ~# t5 I/ E九、关于输入框非空的判断在处理输入框相关业务时,往往会判断输入框未输入值的场景。if(value !== null && value !== undefined && value !== ''){0 Z9 U8 u1 @. X6 `8 a/ R" L
    //...- F5 |* ^+ k+ ^! a5 U" `9 G
}
* a% [) U3 y' r吐槽ES6中新出的空值合并运算符了解过吗,要写那么多条件吗?, \& O# F& B# K  g" j1 H! `
if((value??'') !== ''){( J" ]4 j( l. m% U' Q
  //...
0 @* C$ [9 ]( X" W0 O}
% R2 a! [: V$ A# `! v) b2 z0 Z十、关于异步函数的吐槽异步函数很常见,经常是用 Promise 来实现。
6 [; v( p9 V# }  E0 _8 B
  1. const fn1 = () =>{
    0 i) M( ^" t1 b9 t( _  g0 m
  2.   return new Promise((resolve, reject) => {
    0 [' f' Y3 b' V; j$ D( }
  3.     setTimeout(() => {! I7 b: ^* z/ A/ Z9 Z* R
  4.       resolve(1);
    ' O/ L# r+ p. H0 z. z
  5.     }, 300);
    ; x( `5 D' T9 m; s( Q- r
  6.   });' a: F# D" m$ k; [% r5 c6 f$ q" o: ?
  7. }
    1 x3 v% F/ Q/ h% z- x0 H" M) W
  8. const fn2 = () =>{
    " d9 i* S3 D- D: N3 y5 @9 o+ H. R
  9.   return new Promise((resolve, reject) => {) A. A+ E! F0 N; z$ m3 V  O
  10.     setTimeout(() => {
    " N5 b6 _1 O; w. X( {5 q1 o
  11.       resolve(2);
    ) r  K5 W/ Q) H4 ]
  12.     }, 600);$ X: u3 A& j0 D3 e( v! Y3 q
  13.   });; p! m/ ^* v4 Y! u
  14. }$ v( }% v2 N& Q) q3 L8 E% \
  15. const fn = () =>{
      U" }$ R4 k5 F4 d) n  s6 k, h
  16.    fn1().then(res1 =>{; B9 {4 a; w0 V
  17.       console.log(res1);// 18 d" F0 i* u: p5 S3 V
  18.       fn2().then(res2 =>{' _' ^6 p# {6 Q6 K7 N, T
  19.         console.log(res2)
    * {. c! \( Q( u* f" m! ]
  20.       }): z( k: c1 _9 h7 n" m. i/ Y
  21.    })9 k( g- r4 h/ }4 x/ |. ?/ ]0 J
  22. }
复制代码
- j" |0 |' g0 w: z9 h
吐槽如果这样调用异步函数,不怕形成地狱回调啊!改进$ {7 V' j" D. h7 ^# R
  1. const fn = async () =>{
    ( `2 {5 q# y3 L& o- Y3 b1 ~
  2.   const res1 = await fn1();
    " I' f1 _8 ^0 |! c& y% m
  3.   const res2 = await fn2();; A. [" G4 X' L1 E7 ]2 k; |
  4.   console.log(res1);// 1
    ' g# y) s6 K* F2 T7 p+ M5 |
  5.   console.log(res2);// 2& s! F1 \! t1 `" |
  6. }
复制代码
5 i1 N0 B. J5 {( }- y/ N3 H' W
补充但是要做并发请求时,还是要用到
& m! a4 {  l; l7 o5 D
  1. Promise.all()
    ) @% U3 S' U2 M- h
  2. const fn = () =>{. f8 |! x' Z8 u9 x: `  K/ x* F
  3.    Promise.all([fn1(),fn2()]).then(res =>{
    + r% X( ]9 |4 L% \" P8 \2 Q
  4.        console.log(res);// [1,2]: Q# S9 e% Q3 _9 @/ o9 |1 a  K
  5.    })
    ! C: |* c# p8 D- Y8 P$ U' e3 `
  6. }
复制代码
3 y# V& p* G" b# B
如果并发请求时,只要其中一个异步函数处理完成,就返回结果,要用到Promise.race()。
2 Y4 f6 e- |$ |2 h) d0 y+ a3 q十一、后续欢迎来对以上十点leader的吐槽进行反驳,你的反驳如果有道理的,下次代码评审会上,我替你反驳。此外以上的整理内容有误的地方,欢迎在原文评论中指正,万分感谢。
6 ]; E/ c5 ?# k; @
. G( q* K7 h& X; _7 c9 }1 e- x7 m0 x7 g# {/ @# n7 s

/ h. v8 P2 D8 ^" R9 I( R
中国领先的数字技术资源交流中心!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

5

主题

4

回帖

199

积分

学徒

积分
199
学费
176