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

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

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

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

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

x
20220429_112551_043.jpg             
. Y. y( o1 N  k6 m- G: w不是标题党,这是一位leader在一次代码评审会对小组成员发出的“怒吼”,原因是在代码评审中发现很多地方还是采用ES5的写法,也不是说用ES5写法不行,会有BUG,只是造成代码量增多,可读性变差而已。恰好,这位leader有代码洁癖,面对3~5年经验的成员,还写这种水平的代码,极为不满,不断对代码进行吐槽。不过对于他的吐槽,我感觉还是有很大收获的,故就把leader的吐槽记录下来,分享给掘友们,觉得有收获点个赞,有错误的或者更好的写法,非常欢迎在评论中留言。ps:ES5之后的JS语法统称ES6!!!一、关于取值的吐槽取值在程序中非常常见,比如从对象obj中取值。
  1. const obj = {, M  F+ L/ D. n- s- c1 P
  2.     a:1,2 |4 h* i/ U+ o8 `
  3.     b:2,
    , V( F7 @* c4 d9 }! X: w( Z7 n
  4.     c:3,
    $ o/ N; w1 w* [6 _) @; a. _- G
  5.     d:4,8 Z& r/ O8 H& l* ]6 F6 {0 B
  6.     e:5,$ w$ w1 h5 `5 a9 b
  7. }
复制代码

" X, p) a4 J; b+ Z9 E4 G) S2 U吐槽:
4 H9 H0 v4 t6 y: a+ U# {
  1. const a = obj.a;
    / r. O  @  T2 e% e
  2. const b = obj.b;: p$ }# ^' j% o5 s/ J
  3. const c = obj.c;
    ; c4 c  T9 ?6 i- v$ Q
  4. const d = obj.d;- S2 g% q1 ^3 X4 e" a& k# |! u
  5. const e = obj.e;
复制代码
; X* g& a; C" ^% I" j0 M% p

* l+ |0 ?$ c$ G5 A9 Q2 d2 B或者4 _5 Y: B% b! M( F, z# t6 z7 s
  1. const f = obj.a + obj.d;
    6 c) p. w. R, l( t, ?2 v
  2. const g = obj.c + obj.e;
复制代码
6 Q9 T& x0 j+ [, \
吐槽:“不会用ES6的解构赋值来取值吗?5行代码用1行代码搞定不香吗?直接用对象名加属性名去取值,要是对象名短还好,很长呢?搞得代码中到处都是这个对象名.
. L* b* P* z3 h2 c% u8 m$ k+ R”改进:6 e8 _- N# |, s) `- r$ U) U/ @
  1. const {a,b,c,d,e} = obj;$ z- c: P% t5 v
  2. const f = a + d;2 X( ^9 e: v3 H. L- h$ h+ f
  3. const g = c + e;
复制代码

6 l. r2 r+ D- J9 t- Q$ Z. M& P反驳不是不用ES6的解构赋值,而是服务端返回的数据对象中的属性名不是我想要的,这样取值,不是还得重新创建个遍历赋值。吐槽看来你对ES6的解构赋值掌握的还是不够彻底。如果想创建的变量名和对象的属性名不一致,可以这么写:. s. G8 G* F4 X9 W# t$ b/ c
  1. const {a:a1} = obj;! L! `: t# ]/ B7 U: M! }
  2. console.log(a1);// 1补充ES6的解构赋值虽然好用。但是要注意解构的对象不能为undefined、null。否则会报错,故要给被解构的对象一个默认值。6 x& y2 h# e% b9 _
  3. const {a,b,c,d,e} = obj || {};
复制代码
2 X: J1 P0 E8 @2 \, ~6 Z" G
二、关于合并数据的吐槽比如合并两个数组,合并两个对象。const a = [1,2,3];
, C" n/ \8 e5 }" i4 \
  1. const b = [1,5,6];$ B3 K7 s/ n$ [) y/ g! w
  2. const c = a.concat(b);//[1,2,3,1,5,6]
    5 n* ^4 \; T( L0 a- z3 g
  3. const obj1 = {
    2 a* T6 D# ]! V* M2 K8 P" l) P
  4.   a:1,
    * F  [8 z* Z. H5 d
  5. }1 f5 q6 ?# w8 f/ a- D4 m+ f
  6. const obj2 = {7 P  {7 [7 @* m3 `$ p$ x
  7.   b:1,
    . Z! m* ^9 ~- @2 {  W# S
  8. }' ^$ A/ {" [: V
  9. const obj = Object.assign({}, obj1, obj2);//{a:1,b:1}吐槽ES6的扩展运算符是不是忘记了,还有数组的合并不考虑去重吗?改进const a = [1,2,3];
    2 G1 \: Y% g' y% }; s. c4 W
  10. const b = [1,5,6];) d( E/ c2 [3 O1 j; u
  11. const c = [...new Set([...a,...b])];//[1,2,3,5,6]' @$ j1 n9 @6 p7 Q! r, w
  12. const obj1 = {8 i/ |/ X. L& [5 s' D
  13.   a:1,7 ^, r3 P& t3 R7 w
  14. }
    5 C3 u0 r; g" T
  15. const obj2 = {% [; ]# W1 s* ]2 L8 y& }
  16.   b:1,6 s- Q) e( x/ C2 T! A
  17. }9 ]' e2 ^6 g& v6 e
  18. const obj = {...obj1,...obj2};//{a:1,b:1}
复制代码

# }6 d3 i  Q" X6 M5 W三、关于拼接字符串的吐槽
+ u: n5 d7 Y, x. X" Q. k- _% y
  1. const name = '小明';8 e# D7 C4 X- q* c0 ^7 }  X
  2. const score = 59;7 f) o1 _! k9 N2 P7 N$ A9 Z+ K4 B
  3. let result = '';
    " B0 G: }  }  V5 S/ h/ H
  4. if(score > 60){
    ( ]# W: Y3 t- `3 p5 S
  5.   result = `${name}的考试成绩及格`;
    9 \5 v0 @' v0 L( r" \+ h" I
  6. }else{
    - m# ^, g2 S7 b) E/ B2 l% j
  7.   result = `${name}的考试成绩不及格`;
    & y: Q! q2 L) M/ V
  8. }
复制代码

- }' a3 H  }5 C' b
( o6 H9 N) O9 y% ^吐槽像你们这样用ES6字符串模板,还不如不用,你们根本不清楚在${}中可以做什么操作。在${}中可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性。改进const name = '小明';6 U4 a5 j$ D) ^0 |$ \& V
  1. const score = 59;
    , I. Y4 ^1 e6 H! i% |
  2. const result = `${name}${score > 60?'的考试成绩及格':'的考试成绩不及格'}`;
复制代码
1 t9 E+ }. d, T" v1 i6 I% A/ v: B
四、关于if中判断条件的吐槽if(
# n  P# P6 m+ d% J
  1.     type == 1 ||
    + J$ x, y7 b: E
  2.     type == 2 ||0 P! Q) P  z0 _" U* P  _
  3.     type == 3 ||8 g4 j$ ?* M0 |+ X
  4.     type == 4 ||& w9 i7 ?9 \- ^' d( S/ M/ L5 b
  5. ){( a/ n# x' ~8 E/ [' |
  6.    //...
    5 W' {: _% a$ A# p' g5 O
  7. }
复制代码
8 O. E% T, H: Y
吐槽ES6中数组实例方法includes会不会使用呢?# S1 ^% D$ h6 _/ R2 h+ e: C0 E1 [" M
改进const condition = [1,2,3,4];
+ \) i. _' W: C2 M# M# k
  1. if( condition.includes(type) ){. B0 Y# J6 V) A2 L  {  D! J
  2.    //...
    $ b; M* E0 D0 L3 _' ?
  3. }
复制代码
0 F9 S6 U9 k, a
五、关于列表搜索的吐槽在项目中,一些没分页的列表的搜索功能由前端来实现,搜索一般分为精确搜索和模糊搜索。搜索也要叫过滤,一般用filter来实现。const a = [1,2,3,4,5];
" V" R' v" s/ H" R4 X
  1. const result = a.filter( " E! @$ E1 I& i
  2.   item =>{6 u$ I: S! Z& Y5 Y
  3.     return item === 3& y3 n  ^; u9 |) @4 u! s1 I6 @
  4.   }
    9 C/ [3 H- x3 g& L, r) w" M7 W: s& r
  5. )
复制代码
0 N" I% P2 s. t% q% P) E
吐槽如果是精确搜索不会用ES6中的find吗?性能优化懂么,find方法中找到符合条件的项,就不会继续遍历数组。改进const a = [1,2,3,4,5];
9 Z3 m) d0 y. x4 w9 r( f, }9 R
  1. const result = a.find(
    - C, j2 {' T% V$ J! ^( l
  2.   item =>{
      I: X; M: Q' H8 b& z; \
  3.     return item === 3
    & W  }: O2 S' `$ `' d
  4.   }
    3 ~  C& y- l) d6 e' p$ }
  5. )
复制代码
2 p* b% E% U4 k* t! y
+ ]7 h* X& R& X- G, q0 k, N4 @
六、关于扁平化数组的吐槽一个部门JSON数据中,属性名是部门id,属性值是个部门成员id数组集合,现在要把有部门的成员id都提取到一个数组集合中。
( L4 j2 j3 a5 y
  1. const deps = {
    . n( P9 ~7 G. d
  2. '采购部':[1,2,3],
    : I$ u- j2 L( }& {% L
  3. '人事部':[5,8,12],
    % r3 V% N5 T+ J5 e
  4. '行政部':[5,14,79],- _- }; \' v6 k% m
  5. '运输部':[3,64,105],& b) I# n$ Z& ^: L9 Q9 K
  6. }8 [* k/ Q- [2 E- y8 r' }
  7. let member = [];
    ; k/ A- l. |* t) O
  8. for (let item in deps){
    ' r  D* E3 a$ b; ^7 Z& L1 S
  9.     const value = deps[item];
    % w. V" i* V8 d2 Z! D5 ~, c5 ~
  10.     if(Array.isArray(value)){
    # @8 n" f3 T! S  v  T
  11.         member = [...member,...value]
      o* ~6 G% N4 ~  s5 G  a2 S
  12.     }; i5 F8 j4 \9 ^# R) l) `5 u
  13. }) T7 T& o. `1 O) J  f
  14. member = [...new Set(member)]
复制代码

* v/ n3 o- m1 F2 i* y& v% v# |/ I) d* B
吐槽获取对象的全部属性值还要遍历吗?Object.values忘记了吗?还有涉及到数组的扁平化处理,为啥不用ES6提供的flat方法呢,还好这次的数组的深度最多只到2维,还要是遇到4维、5维深度的数组,是不是得循环嵌套循环来扁平化?1 ]6 Z4 f) v" B1 z. h
改进4 U% J3 A% t+ b3 J4 o( U; A& S
  1. const deps = {; V- I6 \/ S% Z% h- W- z
  2.     '采购部':[1,2,3],- z, t0 a- K! Q' D2 F8 C1 K* l
  3.     '人事部':[5,8,12],
    * }9 m$ b- o9 o! y  K* ?5 u
  4.     '行政部':[5,14,79],; O7 n# h( D2 d
  5.     '运输部':[3,64,105],
    % F4 s- X4 E4 Z0 T4 ?2 M2 O
  6. }+ O" x- C% }: b& z
  7. let member = Object.values(deps).flat(Infinity);
复制代码
9 F9 s8 _# O" ]( n( K2 x5 c, W5 H
其中使用Infinity作为flat的参数,使得无需知道被扁平化的数组的维度。补充flat方法不支持IE浏览器。七、关于获取对象属性值的吐槽const name = obj && obj.name;吐槽ES6中的可选链操作符会使用么?改进const name = obj?.name;八、关于添加对象属性的吐槽当给对象添加属性时,如果属性名是动态变化的,该怎么处理。let obj = {};
" I) F) j( V& Z* Z
  1. let index = 1;
    * B5 Z" Q2 c& P7 i
  2. let key = `topic${index}`;
    # D1 W+ o8 H2 y# u
  3. obj[key] = '话题内容';吐槽为何要额外创建一个变量。不知道ES6中的对象属性名是可以用表达式吗?改进let obj = {};& b5 M; J# k3 {: G9 G1 m2 E
  4. let index = 1;& x: T' K' |& W. g1 Q6 e
  5. obj[`topic${index}`] = '话题内容';
复制代码

. W& m6 g6 \9 p" [2 y! @. P4 X% ~8 d' h" d  V& V8 ~
九、关于输入框非空的判断在处理输入框相关业务时,往往会判断输入框未输入值的场景。if(value !== null && value !== undefined && value !== ''){$ m# m+ u$ Q. e* [( \
    //...
0 u2 f/ u' A6 t}
$ C1 n5 O. X- _& V# v+ V3 x吐槽ES6中新出的空值合并运算符了解过吗,要写那么多条件吗?
, x' t: e& _% n; a% m* Vif((value??'') !== ''){
$ A4 O9 n6 J: O% h+ Z& }4 m! R  //...9 g- U- {1 S7 a* w4 g; ^
}
; e0 l5 s( K; A! R) e  u- M# G十、关于异步函数的吐槽异步函数很常见,经常是用 Promise 来实现。/ }, W0 y3 e' z7 I
  1. const fn1 = () =>{
    8 u# S; [1 A% }3 S
  2.   return new Promise((resolve, reject) => {
    / v# Y& l' O( h0 y# C& S' B: T6 }
  3.     setTimeout(() => {
    ) b; Q+ E0 T9 t5 L  X
  4.       resolve(1);
      j# l& v& v- M: D5 _% t
  5.     }, 300);8 k- ?3 E; l( k4 X# P
  6.   });
    " E! x9 d% \$ m& @
  7. }8 X6 _; i0 ?6 J2 D3 S( \
  8. const fn2 = () =>{
    - e& R% j8 f0 Z7 \
  9.   return new Promise((resolve, reject) => {  W6 ?9 y5 C: o9 Y3 ]  `
  10.     setTimeout(() => {
    ! w4 B6 }& J+ f0 R/ `* C
  11.       resolve(2);
    % h1 f& p5 u% D& ~! w8 X- l* t; {7 |
  12.     }, 600);
    ' y+ ~) `7 H! P6 D5 [: U
  13.   });; p5 F! I8 v7 I3 O+ k) I# m9 [
  14. }/ l+ y% w# S4 q
  15. const fn = () =>{
      j" G" S* c8 n" e+ h
  16.    fn1().then(res1 =>{8 ~8 P2 F7 g4 d* e& I0 P2 D
  17.       console.log(res1);// 1
    ' q+ }8 |4 _! [
  18.       fn2().then(res2 =>{
    3 N2 L( N; j1 B0 o  n
  19.         console.log(res2)% h" S; o3 d) s: {+ @% e; L
  20.       })
    - n& R2 s) z* B2 z- _8 Z' u
  21.    })5 c1 Y2 n- s; M* \
  22. }
复制代码
2 N7 \1 q- n  ]* |
吐槽如果这样调用异步函数,不怕形成地狱回调啊!改进
0 ^9 s* Z( u9 G2 h  V
  1. const fn = async () =>{; K% A1 L2 X' z5 }: X
  2.   const res1 = await fn1();
    9 k1 J% t! C" O: f$ ^2 _3 J
  3.   const res2 = await fn2();
    ) Z  B7 c& {. s, C0 ^
  4.   console.log(res1);// 1
    5 A% p1 D8 Z; a# L2 y
  5.   console.log(res2);// 2& |0 O+ J0 T6 M, {' O
  6. }
复制代码
- ~6 Y* N' F7 F2 P" s& `
补充但是要做并发请求时,还是要用到- j3 `& }& x7 k
  1. Promise.all(); A) q0 j% d/ W
  2. const fn = () =>{
    : g; R' i. _6 v* Y6 J1 t. O1 ~
  3.    Promise.all([fn1(),fn2()]).then(res =>{# ?, r, W  q7 U; M; [1 ?: G9 s) @% @
  4.        console.log(res);// [1,2]
    , B" D; {1 \6 Q9 |( i8 Y
  5.    })
    ; T; J1 M9 j2 o! y/ w, q3 l+ @
  6. }
复制代码
% k7 D! F: ?) S, [) ]5 M
如果并发请求时,只要其中一个异步函数处理完成,就返回结果,要用到Promise.race()。( y& `% a' O4 v7 G# Y  Q$ l
十一、后续欢迎来对以上十点leader的吐槽进行反驳,你的反驳如果有道理的,下次代码评审会上,我替你反驳。此外以上的整理内容有误的地方,欢迎在原文评论中指正,万分感谢。
+ [. A; `. d$ k" J1 J2 l/ E: }4 K- f6 p7 q* U$ o0 G: Q
. J6 s( B" p0 t) ^6 N9 B- i% R

0 y( }4 o  m; ~  y- C. Y" [
中国领先的数字技术资源交流中心!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

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

  • 微信公众号

  • 商务合作