返回顶部
热门问答 更多热门问答
技术文章 更多技术文章

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

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

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

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

x
20220429_112551_043.jpg             ' b# a, N) g* q: G) k
不是标题党,这是一位leader在一次代码评审会对小组成员发出的“怒吼”,原因是在代码评审中发现很多地方还是采用ES5的写法,也不是说用ES5写法不行,会有BUG,只是造成代码量增多,可读性变差而已。恰好,这位leader有代码洁癖,面对3~5年经验的成员,还写这种水平的代码,极为不满,不断对代码进行吐槽。不过对于他的吐槽,我感觉还是有很大收获的,故就把leader的吐槽记录下来,分享给掘友们,觉得有收获点个赞,有错误的或者更好的写法,非常欢迎在评论中留言。ps:ES5之后的JS语法统称ES6!!!一、关于取值的吐槽取值在程序中非常常见,比如从对象obj中取值。
  1. const obj = {
    5 A3 I5 i5 y: a
  2.     a:1,- I0 a4 o; V: S7 p+ F9 h
  3.     b:2,
    4 ]- A! S2 a8 d; j$ v
  4.     c:3,6 c2 z1 t7 ^3 Z. B5 B# O
  5.     d:4,
    4 G2 q- z* j! P- T( R# \
  6.     e:5,
    2 F# E# `( m9 ^9 @' u) i3 H& ]' i
  7. }
复制代码
* E! @% q+ K/ m
吐槽:
' T5 d) [" d7 m: I: ~: L4 `; j  J
  1. const a = obj.a;
    7 L' L1 `/ i( X/ X
  2. const b = obj.b;# @% |$ T' e  S& E6 z2 _# K
  3. const c = obj.c;9 b8 e( E' N; {" v# F$ I
  4. const d = obj.d;
    # v. W1 u0 b: u* z% w5 T* g
  5. const e = obj.e;
复制代码

% F2 r& ~, W- a8 p9 p( Z  \; o  U( u% Q+ T7 x- G% H! M: S
或者, r3 D0 q+ ^6 T& o3 \
  1. const f = obj.a + obj.d;
    ) U9 J1 I* B8 Z: O( k+ M5 ?4 S6 E" r
  2. const g = obj.c + obj.e;
复制代码

5 G( l" n# |/ u: N吐槽:“不会用ES6的解构赋值来取值吗?5行代码用1行代码搞定不香吗?直接用对象名加属性名去取值,要是对象名短还好,很长呢?搞得代码中到处都是这个对象名.3 h2 e6 j" {- @. r+ B, j
”改进:: A" g0 B9 Y8 Z4 a( ~5 L# s. C) u- [# F
  1. const {a,b,c,d,e} = obj;0 \/ f, N6 Z7 C+ ?; d# |/ j
  2. const f = a + d;# A' a4 T; i+ f9 R' k# I
  3. const g = c + e;
复制代码
8 ], y/ H4 h5 [; U+ w
反驳不是不用ES6的解构赋值,而是服务端返回的数据对象中的属性名不是我想要的,这样取值,不是还得重新创建个遍历赋值。吐槽看来你对ES6的解构赋值掌握的还是不够彻底。如果想创建的变量名和对象的属性名不一致,可以这么写:$ {. w/ C$ @2 C6 s; {" J$ |
  1. const {a:a1} = obj;2 P* F# j# f+ s5 X# n3 K
  2. console.log(a1);// 1补充ES6的解构赋值虽然好用。但是要注意解构的对象不能为undefined、null。否则会报错,故要给被解构的对象一个默认值。+ R! M3 j) W- [7 S1 }
  3. const {a,b,c,d,e} = obj || {};
复制代码

7 d3 K' K) p; V6 W+ H2 @二、关于合并数据的吐槽比如合并两个数组,合并两个对象。const a = [1,2,3];
1 @5 b7 a4 s6 }" G9 Z$ o  W
  1. const b = [1,5,6];
    ; c# ]) d" a) J
  2. const c = a.concat(b);//[1,2,3,1,5,6]
    " W0 |8 x! k1 [4 M$ g& N, p& d. X
  3. const obj1 = {
    2 n  {6 k4 {# ]$ n
  4.   a:1,$ u! z# k0 f! P! a. |6 H
  5. }) A! I* b) |  }1 B) f8 g
  6. const obj2 = {
    8 p) g/ H) I  @1 {' q& F
  7.   b:1,) \" d" ~4 r% j3 c5 n' R
  8. }
    7 X' _% e0 ~5 r) g0 }3 M0 R/ U
  9. const obj = Object.assign({}, obj1, obj2);//{a:1,b:1}吐槽ES6的扩展运算符是不是忘记了,还有数组的合并不考虑去重吗?改进const a = [1,2,3];
      u9 o2 P2 J2 N. ?
  10. const b = [1,5,6];
    & y# }: h$ N, n
  11. const c = [...new Set([...a,...b])];//[1,2,3,5,6]
    , o) j9 ^6 U. Y6 l; I# }! H
  12. const obj1 = {
    7 X' {5 P5 k4 h2 n, h" A
  13.   a:1,; a# p% I0 S+ j* Z2 Q$ P# L* r1 l
  14. }4 X& t& T; s, f, h+ W
  15. const obj2 = {) d0 v/ ?1 S; \7 ]. F
  16.   b:1,, |( |$ j+ u- g0 v+ U5 a5 @; V1 Q
  17. }. a1 E" X* e9 R5 j- f1 q5 f& w
  18. const obj = {...obj1,...obj2};//{a:1,b:1}
复制代码
, {8 C' ]5 w. t2 \+ R9 }
三、关于拼接字符串的吐槽
& J. c7 j1 G6 X0 ?3 @8 i. O9 c
  1. const name = '小明';$ w- J+ ~0 F# M- z0 E4 `
  2. const score = 59;
    7 d3 P! D9 b1 `
  3. let result = '';
    % ~* b, k/ E& @4 V
  4. if(score > 60){; B8 l. i* E9 _$ ^- k2 T! t" b, X
  5.   result = `${name}的考试成绩及格`;
    6 w! P& ^- K' U3 f# a; v
  6. }else{
    $ H8 A4 C7 u, s
  7.   result = `${name}的考试成绩不及格`;
      p- e/ z* m, p3 x* }/ O5 Q4 M
  8. }
复制代码
$ @1 {. o/ w+ x/ R
0 k, h" m% E& F+ s
吐槽像你们这样用ES6字符串模板,还不如不用,你们根本不清楚在${}中可以做什么操作。在${}中可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性。改进const name = '小明';
$ j: N! i; ^. w1 n' S
  1. const score = 59;
    6 T' {! ~. G0 H% m) v8 k: M& e" K( T
  2. const result = `${name}${score > 60?'的考试成绩及格':'的考试成绩不及格'}`;
复制代码
) L) O1 ?7 d: \$ U, K& j
四、关于if中判断条件的吐槽if(* E& `. y1 v7 l4 J
  1.     type == 1 ||* M" D9 t1 c6 o; L# Z) ]; M9 Z* w  t
  2.     type == 2 ||7 C, V. Y2 i  u5 }4 q4 v+ P
  3.     type == 3 ||  U; O3 b0 ^& \" w
  4.     type == 4 ||" s6 o: r4 E- y6 K4 ?* a" a4 v
  5. ){, x0 V0 O7 u# E4 y+ O, @7 _
  6.    //...
    $ T' i* w# W) f: L6 @% \$ I
  7. }
复制代码

+ O. n; J& M, f- ~5 }2 K$ x吐槽ES6中数组实例方法includes会不会使用呢?
" a3 B, L6 v; R/ h0 \改进const condition = [1,2,3,4];6 x4 d* I1 I+ f
  1. if( condition.includes(type) ){
    5 |  s1 V) y' {) a( o) a6 K9 Y
  2.    //...( @! ^6 @1 F9 `! G: T
  3. }
复制代码
! C* I1 n% R4 K
五、关于列表搜索的吐槽在项目中,一些没分页的列表的搜索功能由前端来实现,搜索一般分为精确搜索和模糊搜索。搜索也要叫过滤,一般用filter来实现。const a = [1,2,3,4,5];. f- C1 _, Z- |3 I6 |
  1. const result = a.filter( + L/ h. Z. e- S1 v1 G
  2.   item =>{: F& M8 w, F8 M; [* x& P
  3.     return item === 3: K8 t. W  }) V
  4.   }
    5 P5 h( t9 W  ~2 ~" |
  5. )
复制代码

' p) W$ N' o! \6 t! L吐槽如果是精确搜索不会用ES6中的find吗?性能优化懂么,find方法中找到符合条件的项,就不会继续遍历数组。改进const a = [1,2,3,4,5];
# c" B3 O' Z: s3 a) v7 x
  1. const result = a.find(
    + {3 D( S7 p" F
  2.   item =>{8 g, d; L: N1 Q0 }  G; Q- U; E, Z
  3.     return item === 3# q# e4 r' i- B6 a( K: D  j
  4.   }
    ' v& c# q8 L2 c1 U( Z2 ]
  5. )
复制代码

5 N+ s) B3 B  \7 k* ]9 u, b( H) f* I2 K( u
六、关于扁平化数组的吐槽一个部门JSON数据中,属性名是部门id,属性值是个部门成员id数组集合,现在要把有部门的成员id都提取到一个数组集合中。- h% \% A* J6 b: W
  1. const deps = {* N8 P/ A) Z+ |# w3 F: e2 U5 S
  2. '采购部':[1,2,3],
    ! A3 w  a1 a8 M9 P
  3. '人事部':[5,8,12],8 N3 g! V3 V3 t! J/ D6 w- m
  4. '行政部':[5,14,79],& p' [5 U8 s0 S3 n( H. A3 b
  5. '运输部':[3,64,105],9 J  J8 T: o5 e& s6 Z
  6. }8 Q9 g" W# N; ^, W3 |
  7. let member = [];  A+ `# d+ ]# `$ e$ a
  8. for (let item in deps){8 V7 i  e/ Z( I3 u) |: D
  9.     const value = deps[item];
    8 ?) X( T( t& E
  10.     if(Array.isArray(value)){2 _, W* Y3 I9 w/ |
  11.         member = [...member,...value]. s% `( }0 y* B+ {- w
  12.     }
    0 B* r. F% h7 g4 S( F+ h8 g
  13. }- |# Z: v: ~# I: P" O( m0 p. r5 g5 M
  14. member = [...new Set(member)]
复制代码
, h. X( T8 h) r0 _9 w

# X8 G1 ~8 z  {. L4 K吐槽获取对象的全部属性值还要遍历吗?Object.values忘记了吗?还有涉及到数组的扁平化处理,为啥不用ES6提供的flat方法呢,还好这次的数组的深度最多只到2维,还要是遇到4维、5维深度的数组,是不是得循环嵌套循环来扁平化?$ y4 F1 t. S2 m$ F3 _
改进: q& Q7 z( i) i5 `; g0 y  j( `6 m: G
  1. const deps = {
    3 ]  D" p2 y/ R4 p% v+ D
  2.     '采购部':[1,2,3],
    6 x+ {$ x2 H0 ^! }# {6 v: M
  3.     '人事部':[5,8,12],8 q9 L% \& j& R0 o
  4.     '行政部':[5,14,79],
    ) `- S# j" f6 v
  5.     '运输部':[3,64,105],2 ^+ ~9 L) {3 x5 u2 j+ |
  6. }* ]  b/ ?6 R1 o$ y9 k  h5 \
  7. let member = Object.values(deps).flat(Infinity);
复制代码

% T! x' s8 z7 j! i5 L8 _其中使用Infinity作为flat的参数,使得无需知道被扁平化的数组的维度。补充flat方法不支持IE浏览器。七、关于获取对象属性值的吐槽const name = obj && obj.name;吐槽ES6中的可选链操作符会使用么?改进const name = obj?.name;八、关于添加对象属性的吐槽当给对象添加属性时,如果属性名是动态变化的,该怎么处理。let obj = {};/ K9 h1 T  c  M
  1. let index = 1;
    & B4 `& W& V! r
  2. let key = `topic${index}`;
    + \, A4 {% X1 h: V8 b/ Q
  3. obj[key] = '话题内容';吐槽为何要额外创建一个变量。不知道ES6中的对象属性名是可以用表达式吗?改进let obj = {};
    % A0 b( }  @7 @5 Z
  4. let index = 1;
    ! t- S* W5 c" s6 O, [' F' C4 u
  5. obj[`topic${index}`] = '话题内容';
复制代码

7 G) h8 u, Q0 m5 ?4 E# G. H7 ~  t6 c  p! k0 a
九、关于输入框非空的判断在处理输入框相关业务时,往往会判断输入框未输入值的场景。if(value !== null && value !== undefined && value !== ''){& b, V* r: d) q3 Q
    //...1 L8 T/ c" A5 C$ g
}; P! o- F- c/ Y4 M& m2 _9 v2 v
吐槽ES6中新出的空值合并运算符了解过吗,要写那么多条件吗?
1 I: n- K' n' V3 W" _4 E: zif((value??'') !== ''){
0 q, ~% q7 u$ P6 \4 y- H: I8 k  //..." Y+ E6 k8 C% q: @) N& c
}
4 E  a  {& V5 L; K# d9 S1 L十、关于异步函数的吐槽异步函数很常见,经常是用 Promise 来实现。
; k1 D( W' q; z5 J  U% _
  1. const fn1 = () =>{+ W% g7 D7 w; d
  2.   return new Promise((resolve, reject) => {6 I6 G# V; [0 e+ u: y+ ~
  3.     setTimeout(() => {
    * F+ o5 }0 h+ |; V2 g1 h* D" m
  4.       resolve(1);
    : `  [% m3 D) V) _3 v2 T, i# ~: v
  5.     }, 300);
    4 }4 F( c0 n  K% r
  6.   });( d1 S4 H1 ~! ]9 L1 f1 `
  7. }: S  ]  Y: x$ x+ q2 A
  8. const fn2 = () =>{# \" p: _- L7 a$ D( T6 I' P
  9.   return new Promise((resolve, reject) => {0 S8 z0 c; E0 I* _* }% u% _
  10.     setTimeout(() => {
    % I: ?7 @) J! F+ g6 s
  11.       resolve(2);8 c  a, T, p/ r3 K
  12.     }, 600);& l; e: f# ]$ @0 n- Z
  13.   });' _0 ~( z5 d1 H, L' Z1 |# m0 e
  14. }. [1 ~8 E3 G$ p2 v" n/ e
  15. const fn = () =>{" K  F; u4 B4 g  `% v4 @- ?6 o
  16.    fn1().then(res1 =>{
      x) t  f, ?. @' H/ @$ T* k
  17.       console.log(res1);// 1
    - X7 v( v& E" u5 I. ^' r
  18.       fn2().then(res2 =>{* j+ {0 m5 K( o
  19.         console.log(res2)
    . b/ G% _$ T$ X$ M1 D
  20.       })
    5 y" P  y, ]& ]$ G+ M* n
  21.    })' A# p0 y0 a( E9 f0 v
  22. }
复制代码
6 p+ q4 Y1 {' o
吐槽如果这样调用异步函数,不怕形成地狱回调啊!改进6 g  @/ g: O5 D/ W& E3 z
  1. const fn = async () =>{
    & I7 {& W  o- L0 I
  2.   const res1 = await fn1();
    / n2 c+ F$ I% q: \. r, _) t
  3.   const res2 = await fn2();
    9 H# E% x: B# ~
  4.   console.log(res1);// 1
    / o2 T+ [2 M4 |+ p3 `$ D+ S
  5.   console.log(res2);// 2
    / t$ o& L* F, H  H& e' }
  6. }
复制代码
( x, f3 y2 U2 O
补充但是要做并发请求时,还是要用到/ k. E: S  P" X" a9 w) c8 h1 b: i/ \" n
  1. Promise.all(); r! s- `5 X8 H4 y
  2. const fn = () =>{+ ^. ]* m% _" u; k5 q
  3.    Promise.all([fn1(),fn2()]).then(res =>{
    % |% d+ W* s7 h$ L: m3 y
  4.        console.log(res);// [1,2]
    - a5 u, E" `$ T9 `# i8 b
  5.    })
    8 `  m/ Q3 ^; s
  6. }
复制代码

+ r! \. V' a3 F( o6 s% E! z如果并发请求时,只要其中一个异步函数处理完成,就返回结果,要用到Promise.race()。
% M& W! k- U6 k' v, e" k十一、后续欢迎来对以上十点leader的吐槽进行反驳,你的反驳如果有道理的,下次代码评审会上,我替你反驳。此外以上的整理内容有误的地方,欢迎在原文评论中指正,万分感谢。& u+ `7 ^4 [$ h

9 E: u* X: S. V
/ R! m. s7 b. {+ z4 v- @+ N, E1 j$ Z/ n1 C6 Q
中国领先的数字技术资源交流中心!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

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

  • 微信公众号

  • 商务合作