漫潮者,私有云,NAS,新媒体电商.软件开发,商乾

标题: 你会用ES6,那倒是用啊!!! [打印本页]

作者: 商乾美工    时间: 2022-4-29 17:32
标题: 你会用ES6,那倒是用啊!!!
(, 下载次数: 2)             
6 A  X( a; R7 [, X2 {1 U7 P不是标题党,这是一位leader在一次代码评审会对小组成员发出的“怒吼”,原因是在代码评审中发现很多地方还是采用ES5的写法,也不是说用ES5写法不行,会有BUG,只是造成代码量增多,可读性变差而已。恰好,这位leader有代码洁癖,面对3~5年经验的成员,还写这种水平的代码,极为不满,不断对代码进行吐槽。不过对于他的吐槽,我感觉还是有很大收获的,故就把leader的吐槽记录下来,分享给掘友们,觉得有收获点个赞,有错误的或者更好的写法,非常欢迎在评论中留言。ps:ES5之后的JS语法统称ES6!!!一、关于取值的吐槽取值在程序中非常常见,比如从对象obj中取值。
  1. const obj = {$ M. K+ v# a& K+ @5 Z/ T
  2.     a:1,$ E+ O- _  \  l3 i
  3.     b:2,
    / V2 d7 W1 j5 @2 ~# p
  4.     c:3,+ d0 z1 ]# Y1 U$ a
  5.     d:4,) h6 j' X5 g! j+ x7 D. v
  6.     e:5,
    5 f4 J9 d7 d+ w5 b8 K+ b/ [$ q9 o
  7. }
复制代码

" r6 i' ^/ w( ?9 j5 H( Y7 p吐槽:
) E# {) J# z( j
  1. const a = obj.a;
    / J* E' [) T- `; H9 Y
  2. const b = obj.b;
    0 t, R$ _! J) J$ L' {; B
  3. const c = obj.c;7 Q: Y/ q1 W- j3 m& i
  4. const d = obj.d;3 A4 K8 d, S! Y+ J1 d# h2 M
  5. const e = obj.e;
复制代码
3 ~9 g$ \. R: A: T

* W/ {! R) X) X9 `+ j4 z& b- F0 m2 @4 X或者6 r6 ?( G. [0 G* y
  1. const f = obj.a + obj.d;
    5 g) z( q$ t( [" }- c' P% u  ~
  2. const g = obj.c + obj.e;
复制代码

: {* v! ?( b5 O2 T6 W- f吐槽:“不会用ES6的解构赋值来取值吗?5行代码用1行代码搞定不香吗?直接用对象名加属性名去取值,要是对象名短还好,很长呢?搞得代码中到处都是这个对象名.
9 B7 B; p: T: P; ^* r”改进:
$ X9 C" R1 M- V9 A
  1. const {a,b,c,d,e} = obj;
    % K1 U  B3 r: p
  2. const f = a + d;  F& D* A3 `& z5 F
  3. const g = c + e;
复制代码
3 y9 r+ t$ Y  j) k  Y. l$ c5 \
反驳不是不用ES6的解构赋值,而是服务端返回的数据对象中的属性名不是我想要的,这样取值,不是还得重新创建个遍历赋值。吐槽看来你对ES6的解构赋值掌握的还是不够彻底。如果想创建的变量名和对象的属性名不一致,可以这么写:
( K9 W- w4 N; ^7 @/ }
  1. const {a:a1} = obj;
    * K% e. g6 ?/ s% n
  2. console.log(a1);// 1补充ES6的解构赋值虽然好用。但是要注意解构的对象不能为undefined、null。否则会报错,故要给被解构的对象一个默认值。
    ! b& N' W5 D' w# o& ?: R9 V
  3. const {a,b,c,d,e} = obj || {};
复制代码

4 n: v4 t- O, T7 T. c" i二、关于合并数据的吐槽比如合并两个数组,合并两个对象。const a = [1,2,3];) m9 Q, s( ~! I8 z/ `/ i' y5 X+ T5 a
  1. const b = [1,5,6];7 N# \- r. [) h
  2. const c = a.concat(b);//[1,2,3,1,5,6]
    6 G( g8 M% T$ j: X7 k
  3. const obj1 = {/ e, }3 j$ y1 S% K# v
  4.   a:1,
    4 t+ g) l0 k/ E4 f0 |
  5. }& o/ \5 U8 V( N! T
  6. const obj2 = {
    8 L5 ]2 U- M, ~+ S
  7.   b:1,# @0 b3 B5 @6 b+ g- Y) k. s% s
  8. }1 ^' l; G! t: k8 B( S# M5 m; x5 b
  9. const obj = Object.assign({}, obj1, obj2);//{a:1,b:1}吐槽ES6的扩展运算符是不是忘记了,还有数组的合并不考虑去重吗?改进const a = [1,2,3];. W+ a. I1 ]! F
  10. const b = [1,5,6];  `5 M8 u  `6 s0 V4 j1 q3 L
  11. const c = [...new Set([...a,...b])];//[1,2,3,5,6]& I0 g' O8 E+ B3 o
  12. const obj1 = {
    9 I$ G% \4 k) t& u
  13.   a:1,
    1 q# S/ U  a8 M$ [3 D) q& A- ^3 l+ W
  14. }9 o9 Z- Z8 h6 l# C; @8 Q9 J
  15. const obj2 = {
    8 b( W  K$ y0 ~6 T3 `$ u
  16.   b:1,6 X9 N! m" k/ x/ z- G7 r- w* y
  17. }1 j6 m1 p" {% u$ S
  18. const obj = {...obj1,...obj2};//{a:1,b:1}
复制代码
9 Y) s  K. L- {; O4 I2 p' z
三、关于拼接字符串的吐槽1 M5 p- y0 ]. U9 |$ w- @; `( ?
  1. const name = '小明';
    ) ]2 R' N7 \) ]1 c% _3 w
  2. const score = 59;
      j' w# [/ e5 ?0 [: ]8 J
  3. let result = '';" A# O* O' X( L
  4. if(score > 60){
      {; [" }$ j: h# {7 V# t
  5.   result = `${name}的考试成绩及格`; ( x8 G- F6 m* ~
  6. }else{
    ) ?! u9 z$ T6 g% @- p! h0 ?5 _0 d
  7.   result = `${name}的考试成绩不及格`;
    7 m/ H7 E) ?8 l# o) K& E
  8. }
复制代码
% a5 E) L4 d* G) d7 ?0 X: b+ w

8 s  m3 B6 J1 J吐槽像你们这样用ES6字符串模板,还不如不用,你们根本不清楚在${}中可以做什么操作。在${}中可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性。改进const name = '小明';( O8 B' u, }' P  Y1 G$ e
  1. const score = 59;
    1 v. e% ~; k( Y: n3 z  b
  2. const result = `${name}${score > 60?'的考试成绩及格':'的考试成绩不及格'}`;
复制代码

# m5 X5 D. W/ N四、关于if中判断条件的吐槽if(
6 ]# y6 r/ N8 v  k/ B$ R( R4 e
  1.     type == 1 ||
    5 ]! @. B8 p* P. e- {7 ~
  2.     type == 2 ||
    0 q; }- C; u1 k; [% [7 k8 k
  3.     type == 3 ||
    + y2 c" \; b. q* ]- m. J
  4.     type == 4 ||2 n6 \& N9 P+ b4 ~+ i( E1 G" W. ^
  5. ){* N$ k  z4 ]: q) j$ P. i$ U
  6.    //...4 Y* |& e! w) c" n
  7. }
复制代码
; ^& A. R% n5 _9 |9 Z
吐槽ES6中数组实例方法includes会不会使用呢?% [6 }0 C4 x, w3 g, u
改进const condition = [1,2,3,4];( n- d6 W, o. U! D- H
  1. if( condition.includes(type) ){' e9 Y6 O0 N5 [( N& y9 t
  2.    //...
    4 W& @' l- ?, [" y
  3. }
复制代码
' p7 T& W! W1 P; `, E
五、关于列表搜索的吐槽在项目中,一些没分页的列表的搜索功能由前端来实现,搜索一般分为精确搜索和模糊搜索。搜索也要叫过滤,一般用filter来实现。const a = [1,2,3,4,5];
2 ]( @& u6 o& l' ]# i) r& G7 j
  1. const result = a.filter(
    # ^6 R+ k3 ]3 a6 |2 M, T
  2.   item =>{
    - U& Y& A. F/ `4 c
  3.     return item === 3
    % q6 D( s0 f( _' `
  4.   }
    " w' N0 f5 g( O; o0 Q
  5. )
复制代码

7 }5 \/ Y0 k6 T  ]: e; a; L; Q' E) h吐槽如果是精确搜索不会用ES6中的find吗?性能优化懂么,find方法中找到符合条件的项,就不会继续遍历数组。改进const a = [1,2,3,4,5];
0 Y0 t2 ^7 ~9 A4 l  U
  1. const result = a.find( 0 W; h* |+ b0 ^2 N! u
  2.   item =>{# E5 H- _6 K# T
  3.     return item === 3
    1 l: N& b+ u+ X6 o$ \2 x
  4.   }
    6 |  \3 k# p/ f. y% }8 p0 E
  5. )
复制代码
8 T" Y9 Z. c- [) ?

& d1 }! X( L, x& n* L$ B六、关于扁平化数组的吐槽一个部门JSON数据中,属性名是部门id,属性值是个部门成员id数组集合,现在要把有部门的成员id都提取到一个数组集合中。
7 C& z5 g( `3 q  X6 a9 y" a
  1. const deps = {+ v8 B' n$ a9 E# ^2 d6 h! [2 j
  2. '采购部':[1,2,3],
    7 N! @: ^0 H, j( a( s
  3. '人事部':[5,8,12],
    ! Q7 P! A5 j! w/ S8 m4 X" Z
  4. '行政部':[5,14,79],
    + f( d1 X8 c% H
  5. '运输部':[3,64,105],
    0 F, t) h. g: _* S( Y/ P
  6. }1 l' y, N7 C! T$ |( P" o: t
  7. let member = [];8 @7 p# {6 a, n$ y# Z% y; J- g% g
  8. for (let item in deps){
    $ V. B+ c3 z, [$ v$ O8 k
  9.     const value = deps[item];( C; O- R9 I+ s
  10.     if(Array.isArray(value)){
    * u2 }& m) I" y! ^/ ]
  11.         member = [...member,...value]8 U# q. G* t8 l0 ?0 e2 H
  12.     }. c& F8 i4 ?2 {9 o
  13. }
    5 b2 @% s' w! z6 G4 A
  14. member = [...new Set(member)]
复制代码
; m* s. I. G7 S/ g( M; e* h0 h- x

4 V% I: c( Y  y6 T3 x/ [6 c- m吐槽获取对象的全部属性值还要遍历吗?Object.values忘记了吗?还有涉及到数组的扁平化处理,为啥不用ES6提供的flat方法呢,还好这次的数组的深度最多只到2维,还要是遇到4维、5维深度的数组,是不是得循环嵌套循环来扁平化?3 f' m7 s' P% X+ D7 ^
改进& n/ z' e( S: D) o! W+ w7 p( \: ^
  1. const deps = {$ F/ Q/ _, ?0 g- q" Q+ ?
  2.     '采购部':[1,2,3],- j3 M, P3 w* W( E9 e6 X, c5 @
  3.     '人事部':[5,8,12],, }6 w$ D6 K6 B
  4.     '行政部':[5,14,79],
    * H% Y; H5 Y7 v+ M
  5.     '运输部':[3,64,105],/ I+ K) K& c2 ]1 q
  6. }
    / n7 x' N' O" f; {6 Q
  7. let member = Object.values(deps).flat(Infinity);
复制代码

! `3 y; k. ]( r其中使用Infinity作为flat的参数,使得无需知道被扁平化的数组的维度。补充flat方法不支持IE浏览器。七、关于获取对象属性值的吐槽const name = obj && obj.name;吐槽ES6中的可选链操作符会使用么?改进const name = obj?.name;八、关于添加对象属性的吐槽当给对象添加属性时,如果属性名是动态变化的,该怎么处理。let obj = {};! I3 u- t: B- t5 j2 W4 q0 J
  1. let index = 1;
    + o) a3 ]* ~: B, g' c, K2 e
  2. let key = `topic${index}`;# ~) |7 X1 p# L, S
  3. obj[key] = '话题内容';吐槽为何要额外创建一个变量。不知道ES6中的对象属性名是可以用表达式吗?改进let obj = {};
    2 }( k* ?8 u3 w6 x
  4. let index = 1;$ Y! o  K: [( ~3 ~; `
  5. obj[`topic${index}`] = '话题内容';
复制代码
: T) T& u: _. g5 L
* W" ]( N. T# M* |1 x% C
九、关于输入框非空的判断在处理输入框相关业务时,往往会判断输入框未输入值的场景。if(value !== null && value !== undefined && value !== ''){, b2 G+ _9 r: {1 }, e
    //...8 G6 }$ @& L% v7 \* G' U1 v" C9 ?0 g8 Z
}$ y6 o' }- t, v9 ?+ f4 f
吐槽ES6中新出的空值合并运算符了解过吗,要写那么多条件吗?. `: S% P  k0 d$ F/ W+ r
if((value??'') !== ''){
0 `, f0 h7 C5 V. F3 \' m8 s  //...
9 B) h. m  Z, O6 ]- ^}
" N0 j, p9 s; E' _十、关于异步函数的吐槽异步函数很常见,经常是用 Promise 来实现。$ ^& j: k. J% H/ k4 m2 T
  1. const fn1 = () =>{
    ' X9 f' f' w+ a* T8 s9 W
  2.   return new Promise((resolve, reject) => {& i- {+ ?" P& Z+ W. S
  3.     setTimeout(() => {+ m, |6 b' b$ d" T0 [
  4.       resolve(1);
    $ z2 d6 @5 @7 q$ I$ B- @8 V+ M
  5.     }, 300);. }, P+ y6 F' w3 O5 L# b! V
  6.   });. _& S8 N7 R/ K
  7. }
    ! A8 y, x, l: e
  8. const fn2 = () =>{
    7 S1 ^3 e* F0 c# F7 H
  9.   return new Promise((resolve, reject) => {
    2 f/ _5 y# ?. r( G: m; p! |
  10.     setTimeout(() => {3 @3 x: v  e" R" e. v/ r- a
  11.       resolve(2);6 S1 h5 S' F% E  U' l: f$ H1 E1 p
  12.     }, 600);
    & S! Y% X9 ?; T  Y
  13.   });
    % h% P  y" w! o5 T
  14. }
    ! t- v/ \2 k: r
  15. const fn = () =>{
    " y+ N6 o' w! m; {
  16.    fn1().then(res1 =>{# s* ]# _; K; o+ x% {2 k/ Z8 V
  17.       console.log(res1);// 17 {3 P! k7 J4 {6 ~$ z5 ]& A7 g
  18.       fn2().then(res2 =>{( w' ~. Q2 A( J
  19.         console.log(res2)
    & Y5 H# z2 P( A% _- U
  20.       })
    , A5 y! g" `, e& E$ q9 O& _
  21.    })
    ; [1 Y9 |) ~& K# o; \8 e+ \
  22. }
复制代码
' Y: l6 Y, z, M/ }
吐槽如果这样调用异步函数,不怕形成地狱回调啊!改进! c+ C& N5 X$ d; p5 o- z/ u* @
  1. const fn = async () =>{
    9 b8 {3 T; W4 o- B. j9 L! |
  2.   const res1 = await fn1();" \! f$ Q& _( {6 H: f
  3.   const res2 = await fn2();/ a6 h2 d5 y% L) `- [) Y7 }: y% S
  4.   console.log(res1);// 1
    1 ~& \! j6 Z2 p6 E& ?$ \% s
  5.   console.log(res2);// 2( Y5 }* P& _2 F
  6. }
复制代码
% C0 E2 c( }0 C  T% r- q
补充但是要做并发请求时,还是要用到
& Z0 m0 N& c6 J7 V/ ]4 w; M
  1. Promise.all()# ?7 f3 F9 e, P/ D  v
  2. const fn = () =>{7 P3 m) R3 ]2 H' t
  3.    Promise.all([fn1(),fn2()]).then(res =>{# F9 V* f9 Q$ @, {, Y
  4.        console.log(res);// [1,2]( j8 Y% {* ^8 n, q" {, F+ N- k
  5.    })
    4 b  I/ g- i5 C9 S5 J4 c% k# H- _
  6. }
复制代码

8 m0 b! y$ Q2 B: u9 |如果并发请求时,只要其中一个异步函数处理完成,就返回结果,要用到Promise.race()。/ P, |% r% j" N/ h9 A- p
十一、后续欢迎来对以上十点leader的吐槽进行反驳,你的反驳如果有道理的,下次代码评审会上,我替你反驳。此外以上的整理内容有误的地方,欢迎在原文评论中指正,万分感谢。3 v0 d( s/ F9 d5 |) M6 {. x  X+ _  w* s* w
8 B/ ?) m5 [8 z0 U7 }, `$ A' Q6 L* Z

! i$ D0 ~  j( q  B& ~# i$ h
4 F( g' a) g, R/ S




欢迎光临 漫潮者,私有云,NAS,新媒体电商.软件开发,商乾 (https://www.aurrel.com/) Powered by Discuz! X3.4