请选择 进入手机版 | 继续访问电脑版
返回顶部
热门问答 更多热门问答
技术文章 更多技术文章

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

[复制链接]
商乾美工 显示全部楼层 发表于 2022-4-29 17:32:45 |阅读模式 打印 上一主题 下一主题

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

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

x
20220429_112551_043.jpg             
" ~$ n! h- g- {* P: z7 D; W不是标题党,这是一位leader在一次代码评审会对小组成员发出的“怒吼”,原因是在代码评审中发现很多地方还是采用ES5的写法,也不是说用ES5写法不行,会有BUG,只是造成代码量增多,可读性变差而已。恰好,这位leader有代码洁癖,面对3~5年经验的成员,还写这种水平的代码,极为不满,不断对代码进行吐槽。不过对于他的吐槽,我感觉还是有很大收获的,故就把leader的吐槽记录下来,分享给掘友们,觉得有收获点个赞,有错误的或者更好的写法,非常欢迎在评论中留言。ps:ES5之后的JS语法统称ES6!!!一、关于取值的吐槽取值在程序中非常常见,比如从对象obj中取值。
  1. const obj = {8 @7 w# H0 y% P) t  ]
  2.     a:1,
    $ J3 j# ]5 A- c+ Q( F8 i1 Y
  3.     b:2,
      W/ a9 P( T/ a2 l
  4.     c:3,; |3 I  I8 d, Z6 r* z4 A
  5.     d:4,2 ]& d/ R! P* N8 I8 H, A
  6.     e:5,' g5 J* u5 G8 w4 O: m- m7 ]( S! K
  7. }
复制代码
+ L9 j' K) l& y
吐槽:
6 o) j5 E/ t4 T1 Y8 y. ?% ]/ Q
  1. const a = obj.a;7 D( n, h1 |; i8 l% ?6 [7 z/ H5 u2 [
  2. const b = obj.b;" Y5 f; u, S" S' P; o, L# G
  3. const c = obj.c;5 L! b) i. s+ R0 B- u
  4. const d = obj.d;8 {8 x/ l+ W: u  G, f8 |
  5. const e = obj.e;
复制代码

/ E& F! ~9 f. V
. ?9 `6 `  v5 O) p5 _) O1 b或者( X: A; |$ \# L5 G( W8 ?
  1. const f = obj.a + obj.d;
    9 V' W" N6 u  w6 i6 `
  2. const g = obj.c + obj.e;
复制代码

6 K% t) {2 T* n. _3 v吐槽:“不会用ES6的解构赋值来取值吗?5行代码用1行代码搞定不香吗?直接用对象名加属性名去取值,要是对象名短还好,很长呢?搞得代码中到处都是这个对象名.
) t/ W" U( e1 h”改进:) I5 o0 ?- z7 y3 m" d" G1 h6 p
  1. const {a,b,c,d,e} = obj;
    2 R) e# Q. F$ Y* b* m
  2. const f = a + d;& V, n( s6 ~4 k% @
  3. const g = c + e;
复制代码
9 ?8 x. m. j8 ?. J2 {' W, ^
反驳不是不用ES6的解构赋值,而是服务端返回的数据对象中的属性名不是我想要的,这样取值,不是还得重新创建个遍历赋值。吐槽看来你对ES6的解构赋值掌握的还是不够彻底。如果想创建的变量名和对象的属性名不一致,可以这么写:2 s" C, s# Y6 b0 S1 L
  1. const {a:a1} = obj;
    " L9 k4 A! X6 A0 J5 u
  2. console.log(a1);// 1补充ES6的解构赋值虽然好用。但是要注意解构的对象不能为undefined、null。否则会报错,故要给被解构的对象一个默认值。
    ( }/ f# [& G9 H5 G  H
  3. const {a,b,c,d,e} = obj || {};
复制代码

( k4 t& M, U3 G% V; H* M- b2 d5 P二、关于合并数据的吐槽比如合并两个数组,合并两个对象。const a = [1,2,3];8 [, ?9 q8 h2 u6 P* C& ]
  1. const b = [1,5,6];5 j% T  i. _% m% |! r4 S/ H3 P
  2. const c = a.concat(b);//[1,2,3,1,5,6]
    + E. @! A9 l0 e! n; j3 [
  3. const obj1 = {0 F8 P* d) e( Q
  4.   a:1,$ ]5 \& k- r, E+ Y8 O% h
  5. }
    # N( T* Q* F7 `$ i) s
  6. const obj2 = {
    : m, q9 @& o+ A" q
  7.   b:1,
    8 w5 u" Q% d' R9 z
  8. }4 m) ^. s3 ~* i* Z) O$ t9 T
  9. const obj = Object.assign({}, obj1, obj2);//{a:1,b:1}吐槽ES6的扩展运算符是不是忘记了,还有数组的合并不考虑去重吗?改进const a = [1,2,3];9 Q; C4 v" e4 S* i0 p& ^
  10. const b = [1,5,6];
    ( j" ^& a: |& m- F+ j
  11. const c = [...new Set([...a,...b])];//[1,2,3,5,6]
    9 Q7 J& a$ W. T% n
  12. const obj1 = {
    6 [6 T8 c7 Q3 n* F
  13.   a:1,& s7 r9 e+ H, ~8 P- v
  14. }
    5 B+ ~# ~1 E2 Z. [/ O
  15. const obj2 = {! c+ P% C, U: o+ E
  16.   b:1,3 B% ]  J1 _% g. U/ G
  17. }
    6 ?& ]/ w2 U7 `4 y" j/ H' O( w' L( |
  18. const obj = {...obj1,...obj2};//{a:1,b:1}
复制代码

: B6 Q1 c+ G) Y2 N1 z三、关于拼接字符串的吐槽8 v6 x( b( \$ r% o9 b& \/ M
  1. const name = '小明';4 p" [. t: b; B; C4 ^* q
  2. const score = 59;% R" S  q7 D8 C6 _2 N  M# j& ~0 N
  3. let result = '';
    : O7 u+ H$ \& O$ \' L0 g9 B
  4. if(score > 60){( S! o! b) Y  a. Q6 Z$ M% P
  5.   result = `${name}的考试成绩及格`; . v) D  ]! E2 N7 J9 t; Q4 I9 t
  6. }else{
    8 \3 k# U5 t/ t6 b; g
  7.   result = `${name}的考试成绩不及格`; 8 Y! \- \& C5 Q
  8. }
复制代码

: d$ a" N* I4 @6 g
5 P9 Z; B) N. ^1 B; H吐槽像你们这样用ES6字符串模板,还不如不用,你们根本不清楚在${}中可以做什么操作。在${}中可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性。改进const name = '小明';; p8 t# y, x8 D6 R) D8 Z7 \4 S
  1. const score = 59;
    3 A& ]# ~+ w9 F; M
  2. const result = `${name}${score > 60?'的考试成绩及格':'的考试成绩不及格'}`;
复制代码
7 C, T8 }- h  N& d2 l: l0 [* U
四、关于if中判断条件的吐槽if(+ g' K! A$ s, [6 `+ Z$ }% u
  1.     type == 1 ||' O- }* K  {# {/ B; V
  2.     type == 2 ||$ n7 |0 o, s( o" s6 d
  3.     type == 3 ||
    3 U# d8 T6 |8 x) h) @. @
  4.     type == 4 ||' D' j. G+ w- C( v* p' h
  5. ){; ~7 f8 o4 I4 O
  6.    //...
    9 ~; o( U5 q  A0 p1 E& V
  7. }
复制代码
& l1 [+ ]9 d3 ?" @
吐槽ES6中数组实例方法includes会不会使用呢?, B. G+ P) [9 t6 P
改进const condition = [1,2,3,4];# s+ j6 d& h/ V( z0 M$ Q
  1. if( condition.includes(type) ){
    9 H# i! p$ V' |
  2.    //...
      K( ^3 c! g3 M# j8 q7 G/ n
  3. }
复制代码
; e3 ?: m- S, y! F) u* _3 Q, d* X
五、关于列表搜索的吐槽在项目中,一些没分页的列表的搜索功能由前端来实现,搜索一般分为精确搜索和模糊搜索。搜索也要叫过滤,一般用filter来实现。const a = [1,2,3,4,5];
+ u* }3 f+ d$ Y% g
  1. const result = a.filter( 1 Q7 ~) L1 }' l
  2.   item =>{4 _2 k, Y( C: f) e( i' H) C# D% [
  3.     return item === 31 q: m7 {) i9 W* w# W7 D
  4.   }5 N- f$ s5 \% z
  5. )
复制代码
, h- k0 V/ f2 Z
吐槽如果是精确搜索不会用ES6中的find吗?性能优化懂么,find方法中找到符合条件的项,就不会继续遍历数组。改进const a = [1,2,3,4,5];0 X% s% v, R3 A0 ~% l# {4 d4 L
  1. const result = a.find(
    & v& X, v9 i( I) p7 _
  2.   item =>{
    9 \( ?, ~  c7 l
  3.     return item === 3
    ! c. ~; j3 M/ X  T. I+ Z
  4.   }
    ) Q, \# q1 K4 F2 K
  5. )
复制代码
7 m  J' p0 j! ?
3 M. P) H, t7 {0 f* d
六、关于扁平化数组的吐槽一个部门JSON数据中,属性名是部门id,属性值是个部门成员id数组集合,现在要把有部门的成员id都提取到一个数组集合中。
/ n* Y2 U8 x# p. t
  1. const deps = {  @+ X$ g( c: N5 g4 T' X6 ]
  2. '采购部':[1,2,3],$ w+ a! h- @  P+ O5 R" b/ u. C! h
  3. '人事部':[5,8,12],2 d! t; ^3 |+ f$ @: u1 |
  4. '行政部':[5,14,79],7 J* x" T$ U2 P2 W. }1 I9 K
  5. '运输部':[3,64,105],/ |" u% c" L+ y1 m
  6. }% w3 N& {3 p) ^/ Z9 k3 Y' ~0 k2 q
  7. let member = [];
    1 A2 {5 f: h8 P9 M( |. A: R
  8. for (let item in deps){
    8 f5 j4 J% Z( z2 ?
  9.     const value = deps[item];
    # p$ j& I* v/ S8 e6 a* T+ _
  10.     if(Array.isArray(value)){
    : W1 U0 ^9 @8 a: w& g4 E
  11.         member = [...member,...value]
    % g2 M5 g+ m, P# X7 `4 }' A) Y7 q
  12.     }8 a( x- s) y8 d: i( ~3 J
  13. }
    9 }  V4 k& W8 y% v/ x! v6 o* M( ?
  14. member = [...new Set(member)]
复制代码
1 \7 m1 d% B& q" q

9 ~+ h* N. q5 Y% i吐槽获取对象的全部属性值还要遍历吗?Object.values忘记了吗?还有涉及到数组的扁平化处理,为啥不用ES6提供的flat方法呢,还好这次的数组的深度最多只到2维,还要是遇到4维、5维深度的数组,是不是得循环嵌套循环来扁平化?- I% u9 _9 |- c8 S- j% G
改进
. h, A  i) ?5 N% O' \% f
  1. const deps = {
    0 }: \8 ^7 y3 k7 }3 g7 u
  2.     '采购部':[1,2,3],! u2 `: L  l6 L) f0 j; Q5 _7 o
  3.     '人事部':[5,8,12],4 [' I1 C8 W! m, k
  4.     '行政部':[5,14,79],* y) B4 E3 E% t+ j: u1 m$ i
  5.     '运输部':[3,64,105],. k6 {- U5 e! b' h( v
  6. }
    3 Z+ e0 A; A6 j4 z
  7. let member = Object.values(deps).flat(Infinity);
复制代码

" J2 L* \6 k& O( E4 f其中使用Infinity作为flat的参数,使得无需知道被扁平化的数组的维度。补充flat方法不支持IE浏览器。七、关于获取对象属性值的吐槽const name = obj && obj.name;吐槽ES6中的可选链操作符会使用么?改进const name = obj?.name;八、关于添加对象属性的吐槽当给对象添加属性时,如果属性名是动态变化的,该怎么处理。let obj = {};2 B5 ]3 B; |: e& y6 |
  1. let index = 1;
    * e) h/ N; X2 S9 L
  2. let key = `topic${index}`;" w0 X% M9 v: q1 w/ y/ S  D7 i
  3. obj[key] = '话题内容';吐槽为何要额外创建一个变量。不知道ES6中的对象属性名是可以用表达式吗?改进let obj = {};& O2 ^( b3 Z: R6 D3 _0 u( m
  4. let index = 1;6 h4 K' y1 C' \# K$ J8 ]3 q9 ?, M
  5. obj[`topic${index}`] = '话题内容';
复制代码

/ s* g, [7 O& W  w$ v- R( c3 b# B) y3 ?
九、关于输入框非空的判断在处理输入框相关业务时,往往会判断输入框未输入值的场景。if(value !== null && value !== undefined && value !== ''){
7 I' O1 K" z2 F, C# t/ `    //...
. Y; K  }6 ~8 B6 W9 ?}
7 h1 K4 ?* A) g2 k0 d吐槽ES6中新出的空值合并运算符了解过吗,要写那么多条件吗?
! a; @, U6 @  q1 u  x1 eif((value??'') !== ''){- l+ j8 x, [" H) G' z1 s
  //...8 m% C6 p* R8 @: {, r
}
8 K# X* U9 Y0 B% x5 ~十、关于异步函数的吐槽异步函数很常见,经常是用 Promise 来实现。9 u2 ~0 a. T( X$ n5 R9 }
  1. const fn1 = () =>{
    5 `3 ?$ s3 m% G! K( l! W
  2.   return new Promise((resolve, reject) => {$ e4 N5 R9 c0 G1 @
  3.     setTimeout(() => {
    $ V7 O$ O: K0 {' {) z9 [9 g2 [
  4.       resolve(1);6 y# i4 w+ [9 y3 n: G  s; L
  5.     }, 300);
    ( j$ D4 d! p/ M
  6.   });2 x- ]3 X& K# ?' M$ p  p) n0 g7 u
  7. }
    ( K( i) P) R0 f8 G  c. ~
  8. const fn2 = () =>{
    % J$ t, A5 c. I# s% q" M2 q8 z
  9.   return new Promise((resolve, reject) => {( Q3 U1 R* T5 J: t4 @7 Z
  10.     setTimeout(() => {
    & R! ?1 B7 n2 w0 }; @
  11.       resolve(2);9 }& f6 `7 \. C8 |: O0 X
  12.     }, 600);
    ' }. w' @0 y( A4 ~, i  j
  13.   });
    + x! V! r4 o/ ]' L. I
  14. }/ Z; w; N1 c/ \
  15. const fn = () =>{
    ; U' I5 m' r; M9 q+ ~
  16.    fn1().then(res1 =>{0 g$ p1 U3 y9 {& K
  17.       console.log(res1);// 1
    # l9 ^" l$ _* y4 V6 _* y
  18.       fn2().then(res2 =>{
    0 G7 X. [4 D& l# \/ E
  19.         console.log(res2)
    8 `& h9 Q, O3 u7 x: R0 _0 E
  20.       })6 O( I  d- y& h
  21.    })
    1 f  T0 G2 E5 b) q  Z! ?
  22. }
复制代码

9 _- p- G. M9 D吐槽如果这样调用异步函数,不怕形成地狱回调啊!改进# P: }: Q- \/ B  o2 b  _
  1. const fn = async () =>{% P5 r5 n2 i- r
  2.   const res1 = await fn1();
    & }  G0 l( e8 p9 O" Y, D
  3.   const res2 = await fn2();0 a, k) z; G4 f) g
  4.   console.log(res1);// 1
    / E. T. Z) _, D9 ~6 J3 U! G5 J" W% }* U
  5.   console.log(res2);// 2
    0 V7 N7 m* z! g
  6. }
复制代码

7 e3 v6 N& i3 ~9 L8 c补充但是要做并发请求时,还是要用到" s& U' \. n. Q2 Q9 F
  1. Promise.all()
    & G( s- i! l9 r7 o9 Q5 M
  2. const fn = () =>{  _; E3 g: J7 `0 a! e! I- L
  3.    Promise.all([fn1(),fn2()]).then(res =>{1 V) W( F9 {/ F% E4 q+ o  }: ?
  4.        console.log(res);// [1,2], M" @% i7 n3 V+ ?
  5.    })
    - x3 `$ o) @: Y7 _
  6. }
复制代码

/ b( t; E- N5 w& o: a" {如果并发请求时,只要其中一个异步函数处理完成,就返回结果,要用到Promise.race()。
. s& S: G; H( F/ N; C) d2 j十一、后续欢迎来对以上十点leader的吐槽进行反驳,你的反驳如果有道理的,下次代码评审会上,我替你反驳。此外以上的整理内容有误的地方,欢迎在原文评论中指正,万分感谢。# N3 M0 N, t: f: }$ z+ `

. C7 D- w" r- u/ C4 W) J  i  ]0 m& b- V! F
3 h4 T: m# ]/ V+ @4 U& b# ~
做电商找商乾,中国最大的电商技术资源交流中心!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

商乾全球电商人、电商交流学习与电商实战技术分享、电商爬虫、生活交流专业网站
  • 官方手机版

  • 微信公众号

  • 商务合作