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

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

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

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

×
20220429_112551_043.jpg             6 z+ G0 Q, x" E- F
不是标题党,这是一位leader在一次代码评审会对小组成员发出的“怒吼”,原因是在代码评审中发现很多地方还是采用ES5的写法,也不是说用ES5写法不行,会有BUG,只是造成代码量增多,可读性变差而已。恰好,这位leader有代码洁癖,面对3~5年经验的成员,还写这种水平的代码,极为不满,不断对代码进行吐槽。不过对于他的吐槽,我感觉还是有很大收获的,故就把leader的吐槽记录下来,分享给掘友们,觉得有收获点个赞,有错误的或者更好的写法,非常欢迎在评论中留言。ps:ES5之后的JS语法统称ES6!!!一、关于取值的吐槽取值在程序中非常常见,比如从对象obj中取值。
  1. const obj = {9 b$ O6 H6 ^" ~0 n. b" B) F
  2.     a:1,
    4 x2 Q, z+ n0 y3 f
  3.     b:2,) Y; l9 g% ~  p* d
  4.     c:3,
      f5 N- P0 Q2 @* u/ y1 m- \! b* q
  5.     d:4,, r. D8 {: k: y6 b
  6.     e:5," Z. n0 j& I" K
  7. }
复制代码

+ @; u$ v* U* b吐槽:
& |* i$ z; g9 s! f
  1. const a = obj.a;
    % g3 n* P* y  N. c/ y
  2. const b = obj.b;" o4 B( f# g" U; K4 E% J7 x
  3. const c = obj.c;0 }6 J" f; H, r% F% \
  4. const d = obj.d;" ?: h$ A1 w) z6 u2 R9 s4 P! Z
  5. const e = obj.e;
复制代码

5 ?- g5 Q8 c0 N# ?! a" z( Q" Y- N  t* e4 R
或者0 p8 j! N  ~0 N$ E: ]4 Z3 K3 G
  1. const f = obj.a + obj.d;* Y/ }9 w) t& P4 n4 Y! B
  2. const g = obj.c + obj.e;
复制代码
3 z" Q. [0 @! B8 f6 h, b8 j: `
吐槽:“不会用ES6的解构赋值来取值吗?5行代码用1行代码搞定不香吗?直接用对象名加属性名去取值,要是对象名短还好,很长呢?搞得代码中到处都是这个对象名.
5 |& ?6 F' D5 n  V. M; I”改进:- N% g" e" o* Q+ A1 d
  1. const {a,b,c,d,e} = obj;' K% e8 p, K  X: G! X
  2. const f = a + d;
    1 u' z- J/ f4 ?+ W# o2 f; h: L' @
  3. const g = c + e;
复制代码

; O6 c8 v, {! c1 @9 V% W: t反驳不是不用ES6的解构赋值,而是服务端返回的数据对象中的属性名不是我想要的,这样取值,不是还得重新创建个遍历赋值。吐槽看来你对ES6的解构赋值掌握的还是不够彻底。如果想创建的变量名和对象的属性名不一致,可以这么写:& I5 d5 Q: v/ Q. @; a6 [
  1. const {a:a1} = obj;' B* F2 X0 ]) z4 O/ H* g% `
  2. console.log(a1);// 1补充ES6的解构赋值虽然好用。但是要注意解构的对象不能为undefined、null。否则会报错,故要给被解构的对象一个默认值。: H$ K- b7 [  x, X2 y
  3. const {a,b,c,d,e} = obj || {};
复制代码

" b& d+ r# |% Y+ K+ r二、关于合并数据的吐槽比如合并两个数组,合并两个对象。const a = [1,2,3];
8 z$ |8 j- Z7 Y9 @8 N6 g, U
  1. const b = [1,5,6];4 F% e4 A. f6 T$ E+ O
  2. const c = a.concat(b);//[1,2,3,1,5,6]3 c) F3 q1 U( j0 s/ H
  3. const obj1 = {
    6 N2 T7 Y1 r7 T# K3 D
  4.   a:1,
    8 ]/ s2 s& @/ d
  5. }
    $ ~& |$ @; |& k& I( W
  6. const obj2 = {7 t+ ?" J( \$ k# `6 r4 a
  7.   b:1,! F. V( {$ s! Y! u% l
  8. }  Z' o) l# \$ s9 e! k1 m% w+ g8 a
  9. const obj = Object.assign({}, obj1, obj2);//{a:1,b:1}吐槽ES6的扩展运算符是不是忘记了,还有数组的合并不考虑去重吗?改进const a = [1,2,3];& t+ y# l0 ~1 e; a
  10. const b = [1,5,6];
    " Q. Y8 A1 O' V& A# J& v
  11. const c = [...new Set([...a,...b])];//[1,2,3,5,6]
    % p* {0 S: y0 ~1 I
  12. const obj1 = {+ I8 ^# J" E& E$ e7 w+ N9 a  R
  13.   a:1,$ u$ M: c- {( x4 U3 e- M
  14. }) I( R. a( ^& B3 k# z
  15. const obj2 = {
    . S) S7 M4 v0 M, E: K9 j
  16.   b:1,
    7 g9 s' v% l- \9 X& K& `
  17. }
    ' n! g1 L/ X' T* h' w  A0 D  {
  18. const obj = {...obj1,...obj2};//{a:1,b:1}
复制代码

* c1 A: b) N  Q+ f; q; Z三、关于拼接字符串的吐槽
0 k9 M5 A! k* t  r3 T1 A
  1. const name = '小明';
    ( m+ e# J! {5 |! r! I
  2. const score = 59;2 T* R' d9 [4 y1 X# P. b6 `
  3. let result = '';
    9 Z4 Q7 g' L! }6 ~; C* l
  4. if(score > 60){6 W$ N0 A* e8 j
  5.   result = `${name}的考试成绩及格`; 6 a3 N" F/ L5 W' J
  6. }else{6 l) g0 f3 p$ \
  7.   result = `${name}的考试成绩不及格`; - z) [* m* q" D2 Q: ~/ ~1 U6 }
  8. }
复制代码

, x/ i7 O+ f) h0 X
0 L# H' \: S! \$ e% @0 X吐槽像你们这样用ES6字符串模板,还不如不用,你们根本不清楚在${}中可以做什么操作。在${}中可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性。改进const name = '小明';
1 [1 r1 w3 p7 `5 z$ L
  1. const score = 59;
    - y5 o+ x1 e8 Z- `( E8 @+ s
  2. const result = `${name}${score > 60?'的考试成绩及格':'的考试成绩不及格'}`;
复制代码
7 K/ _2 q$ }. t+ X1 p* |$ N! ^
四、关于if中判断条件的吐槽if(
& m" p; S- r5 f8 G4 {
  1.     type == 1 ||
    # Z4 D6 s+ l# p: R# W- b" x) k  c' S( M
  2.     type == 2 ||$ M  f9 N) p' W* P, E
  3.     type == 3 ||$ x5 g+ _+ `( Q: d
  4.     type == 4 ||' }6 ?0 N7 X0 e: r- I
  5. ){
    ( x, [& N% m/ P7 Y6 }' d
  6.    //...# X8 i; V+ {6 A; R- s; x! m* Q8 W* B
  7. }
复制代码

: v# e# Y% w/ h: T( ~, |吐槽ES6中数组实例方法includes会不会使用呢?
4 x5 a! J6 |' ^改进const condition = [1,2,3,4];2 J% b2 m: B) a- G( u
  1. if( condition.includes(type) ){
    2 h- Y' X& K% G
  2.    //...
    & Y4 h  r6 ?; r5 q. P
  3. }
复制代码

9 p$ A3 h( }8 x4 _4 I7 M8 y五、关于列表搜索的吐槽在项目中,一些没分页的列表的搜索功能由前端来实现,搜索一般分为精确搜索和模糊搜索。搜索也要叫过滤,一般用filter来实现。const a = [1,2,3,4,5];4 f0 G& K( {" m. b# q/ h& O
  1. const result = a.filter(
    7 w- \8 X+ w8 C. K: u
  2.   item =>{
    1 i4 ^$ ?7 ~! Y" L4 G1 N) _9 a1 _7 }
  3.     return item === 3
    , g& W2 k- \- m' }* q4 ~% @
  4.   }$ R1 Z0 _' t. p0 _1 l' P
  5. )
复制代码

# x% b4 f1 T8 o; N吐槽如果是精确搜索不会用ES6中的find吗?性能优化懂么,find方法中找到符合条件的项,就不会继续遍历数组。改进const a = [1,2,3,4,5];
) p8 v3 b4 b+ D# o) g# a; q
  1. const result = a.find( . S5 ?, y+ U: \! i3 {  D& R
  2.   item =>{
      p& e+ W# U7 M% V8 J4 d
  3.     return item === 3% y4 c9 D3 f3 H4 e& Y" E
  4.   }
    ) Z- ~0 o; W3 [: V: M/ H
  5. )
复制代码
- q5 B0 _/ Q' ~( H* I8 j
2 E# B  ?* t$ J  L' X
六、关于扁平化数组的吐槽一个部门JSON数据中,属性名是部门id,属性值是个部门成员id数组集合,现在要把有部门的成员id都提取到一个数组集合中。, L5 R! J8 v0 M) t) J( o7 L
  1. const deps = {1 I  L4 R0 e% a8 K+ P
  2. '采购部':[1,2,3],
    1 F( \1 S& Q3 u, l, ^7 K( t
  3. '人事部':[5,8,12],6 F; P6 x5 O6 a# \" x
  4. '行政部':[5,14,79],5 J; A+ v) l, W  l- X1 t$ r
  5. '运输部':[3,64,105],0 `- T; \2 u% r' D
  6. }
    * ~' l9 _% L& \1 w% R" t
  7. let member = [];( q) Z7 u, n, l+ w
  8. for (let item in deps){
    ' {% x+ y3 _+ P. v
  9.     const value = deps[item];; ~6 v$ M8 n& m' J
  10.     if(Array.isArray(value)){
    , N) p* @) k5 U5 W9 h3 u' U- m% u
  11.         member = [...member,...value]
    , i% U& q8 F0 u% l
  12.     }
    6 X( `5 G0 L2 N
  13. }/ H* z. W% s( u. Q  P1 t
  14. member = [...new Set(member)]
复制代码
+ W, u- C) t" o. x2 L
* N; s1 @/ p5 A
吐槽获取对象的全部属性值还要遍历吗?Object.values忘记了吗?还有涉及到数组的扁平化处理,为啥不用ES6提供的flat方法呢,还好这次的数组的深度最多只到2维,还要是遇到4维、5维深度的数组,是不是得循环嵌套循环来扁平化?5 V! x& Z/ {2 m' `$ f% N: v. v
改进3 N* o4 v( l9 {- Z5 J$ ~, m
  1. const deps = {( @8 O! [  s5 C# ]; [) E
  2.     '采购部':[1,2,3],
    ' ~; z; x3 c+ y5 l/ U- _
  3.     '人事部':[5,8,12],' `- b* \# b6 f  D6 V3 c
  4.     '行政部':[5,14,79],
    * y1 h  `( Z2 I% d# C
  5.     '运输部':[3,64,105],* J, n8 I# V" j2 [
  6. }8 h6 v6 S. e% d) U+ S2 W: M
  7. let member = Object.values(deps).flat(Infinity);
复制代码

2 m4 T  d" _7 J4 J# o其中使用Infinity作为flat的参数,使得无需知道被扁平化的数组的维度。补充flat方法不支持IE浏览器。七、关于获取对象属性值的吐槽const name = obj && obj.name;吐槽ES6中的可选链操作符会使用么?改进const name = obj?.name;八、关于添加对象属性的吐槽当给对象添加属性时,如果属性名是动态变化的,该怎么处理。let obj = {};
6 z0 O2 D' k) s! G
  1. let index = 1;
    ! H8 R2 Q* B1 q& w# ?8 x3 j4 _
  2. let key = `topic${index}`;
    ! L+ e+ a4 I, F) W5 N! d' A
  3. obj[key] = '话题内容';吐槽为何要额外创建一个变量。不知道ES6中的对象属性名是可以用表达式吗?改进let obj = {};
    % \6 A7 O) m% _; h1 O) ]2 s
  4. let index = 1;2 X' S# }4 P9 b! ~2 m0 n
  5. obj[`topic${index}`] = '话题内容';
复制代码
1 C5 _9 `3 T2 z1 S+ f! @# O8 r
. |8 x1 e8 v( P, A
九、关于输入框非空的判断在处理输入框相关业务时,往往会判断输入框未输入值的场景。if(value !== null && value !== undefined && value !== ''){
% l7 J4 C+ p! P! u, Q    //...; _: u/ e/ \6 l# e
}
( m; m& o( E- |/ P& B9 w吐槽ES6中新出的空值合并运算符了解过吗,要写那么多条件吗?4 [$ L# u, _- T9 ^5 @. Z7 j6 u2 E
if((value??'') !== ''){
2 @# y' r& e( Z' S7 A2 m1 L  //...7 R7 Q3 `; u2 T8 J
}' T. ^% Y" U( H5 k7 a. w
十、关于异步函数的吐槽异步函数很常见,经常是用 Promise 来实现。
- J/ g0 V9 k* \# X; J
  1. const fn1 = () =>{
    + o4 n( h' ~! e, h3 v9 R
  2.   return new Promise((resolve, reject) => {
    , I2 u" |! K* p  t. Q: t& l) b7 u
  3.     setTimeout(() => {
    % G( I$ {. v2 r* Z& ~) H
  4.       resolve(1);  {) y4 L1 o  d* ~
  5.     }, 300);
    4 {+ ]7 T; |; l4 e9 C3 l8 o5 \
  6.   });4 u$ i7 V3 c" x  {( l
  7. }+ a& t8 m6 {$ m) b1 R
  8. const fn2 = () =>{3 |- I9 E! C' C7 D7 O
  9.   return new Promise((resolve, reject) => {
    , ^( e, ]" L( O* U7 M
  10.     setTimeout(() => {7 e! v6 `) _' B3 K; x
  11.       resolve(2);
    ; N3 x; _) ^7 x8 C
  12.     }, 600);
    4 Q: q& k1 u# D+ I
  13.   });
    " T, X$ d5 u) u
  14. }
    . a% n6 E+ s9 s2 }
  15. const fn = () =>{  O( q. }. P$ `4 B# p: B
  16.    fn1().then(res1 =>{" L* J( x0 N' l0 i/ [* N
  17.       console.log(res1);// 1; n& t& ]  g$ u
  18.       fn2().then(res2 =>{
    / }4 t$ x) g; Z" G9 G' }
  19.         console.log(res2)7 _0 w' y9 L  ?3 E6 R8 D
  20.       })
    5 p7 s6 _  z7 e4 U( G0 g4 z
  21.    })8 i: A1 E/ O- p! n0 ?# v
  22. }
复制代码
' J4 L+ N( ?; k5 ]% G& t
吐槽如果这样调用异步函数,不怕形成地狱回调啊!改进9 b  e& y5 H1 }4 X& S) d5 k
  1. const fn = async () =>{" l- {: n% r( f- y$ P
  2.   const res1 = await fn1();
    * _: w: D5 ]; n; ]% d8 n) v2 _: n# J  ?
  3.   const res2 = await fn2();
    # r" ]9 m1 h6 X/ e5 z% l( g( v6 K
  4.   console.log(res1);// 1
    8 C1 X+ L" m0 q1 s) }) F
  5.   console.log(res2);// 2
    ! F4 C) O8 g, d% B( l& H
  6. }
复制代码

* f- `; i/ t! ~6 I, w% p补充但是要做并发请求时,还是要用到: Y9 ]9 L; G& x! Z  T: }1 ?
  1. Promise.all()
    , b- x0 U9 H2 A5 p$ ]
  2. const fn = () =>{; O4 e* m( F  y6 I5 h$ P9 t
  3.    Promise.all([fn1(),fn2()]).then(res =>{1 N* |& L/ {- A- w0 A& N3 p
  4.        console.log(res);// [1,2]
    2 I! ^8 X* a4 E+ k3 S
  5.    }) ; }' M3 ^4 g+ k. T& b0 a
  6. }
复制代码

# \" r0 q: M; o0 ?7 M如果并发请求时,只要其中一个异步函数处理完成,就返回结果,要用到Promise.race()。) s8 P# I5 u6 @. O
十一、后续欢迎来对以上十点leader的吐槽进行反驳,你的反驳如果有道理的,下次代码评审会上,我替你反驳。此外以上的整理内容有误的地方,欢迎在原文评论中指正,万分感谢。! ?9 m  I3 X6 ?
. f  c5 R+ N* p2 ?
) C1 g$ H  F! K' M8 [( R6 G6 Y
* D( s* Q) w6 B1 v8 v6 E0 l: o4 b
中国领先的数字技术资源交流中心!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

5

主题

4

回帖

199

积分

学徒

积分
199
学费
176