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

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

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

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

×
20220429_112551_043.jpg             4 N4 \, a; I  x- o
不是标题党,这是一位leader在一次代码评审会对小组成员发出的“怒吼”,原因是在代码评审中发现很多地方还是采用ES5的写法,也不是说用ES5写法不行,会有BUG,只是造成代码量增多,可读性变差而已。恰好,这位leader有代码洁癖,面对3~5年经验的成员,还写这种水平的代码,极为不满,不断对代码进行吐槽。不过对于他的吐槽,我感觉还是有很大收获的,故就把leader的吐槽记录下来,分享给掘友们,觉得有收获点个赞,有错误的或者更好的写法,非常欢迎在评论中留言。ps:ES5之后的JS语法统称ES6!!!一、关于取值的吐槽取值在程序中非常常见,比如从对象obj中取值。
  1. const obj = {
    . q( ?8 E7 }  M( g
  2.     a:1,& w& V$ ?! `1 A3 `$ a( y5 n9 @0 @
  3.     b:2,- i7 r, @& ^/ X& w1 {9 w
  4.     c:3," C# ^9 A- R6 ^9 m3 u
  5.     d:4,
    0 E1 a& }* m6 F8 G3 \  |$ n7 d. C
  6.     e:5,
    , S5 ?) O6 a5 a
  7. }
复制代码

& z4 G6 u4 H: R0 T6 C* a吐槽:
# D* {- G& h  I* X8 o
  1. const a = obj.a;( n) r: z) ]1 s( I% G
  2. const b = obj.b;
    : C& H7 ], J5 {1 o6 f' l/ D
  3. const c = obj.c;
      ^. Q& f. U2 o; M$ O. N# O+ J
  4. const d = obj.d;
    + N/ ^% o' G( ~" K( e
  5. const e = obj.e;
复制代码
8 a$ e8 t" L- J* V
  X1 k. d: T/ S0 e: H# g0 h& d
或者2 w/ |: }1 Z' G+ Y
  1. const f = obj.a + obj.d;
    * a* Z& i$ f" `! }3 E7 r7 r
  2. const g = obj.c + obj.e;
复制代码

2 Z; I" U; K  H. X: q$ e吐槽:“不会用ES6的解构赋值来取值吗?5行代码用1行代码搞定不香吗?直接用对象名加属性名去取值,要是对象名短还好,很长呢?搞得代码中到处都是这个对象名.; O9 S: q: P  T9 u2 _" |
”改进:9 c2 h* ^3 O  Q2 ?. P
  1. const {a,b,c,d,e} = obj;; k! b3 Z# ]9 }& n
  2. const f = a + d;$ h/ M* \5 S9 x. y
  3. const g = c + e;
复制代码

# E5 w0 V& H3 P0 T* _; E反驳不是不用ES6的解构赋值,而是服务端返回的数据对象中的属性名不是我想要的,这样取值,不是还得重新创建个遍历赋值。吐槽看来你对ES6的解构赋值掌握的还是不够彻底。如果想创建的变量名和对象的属性名不一致,可以这么写:
  Q: N9 q- t) q
  1. const {a:a1} = obj;! w- _$ s$ ~4 x# N
  2. console.log(a1);// 1补充ES6的解构赋值虽然好用。但是要注意解构的对象不能为undefined、null。否则会报错,故要给被解构的对象一个默认值。
    $ N+ H) @, p! N( W3 K) `
  3. const {a,b,c,d,e} = obj || {};
复制代码
2 A/ c* R# ~: z3 v2 o
二、关于合并数据的吐槽比如合并两个数组,合并两个对象。const a = [1,2,3];
6 R* {+ q3 N  @3 w
  1. const b = [1,5,6];
    * u4 M. b: S, B! ]8 x1 ~. e, o
  2. const c = a.concat(b);//[1,2,3,1,5,6]  `7 f9 G* h7 @# a, t. `$ M
  3. const obj1 = {# n5 ^& Z0 F+ I4 r4 y
  4.   a:1,
    $ Z$ v2 z, J; P- F3 U+ D! e/ Y
  5. }  d7 S" f& o( y3 \! ~+ c3 {
  6. const obj2 = {+ _0 T# [6 H$ y7 Y
  7.   b:1,# d  Y* }9 a5 D' o
  8. }7 S) |1 q# l- {7 ^( z) k+ I4 n( ^
  9. const obj = Object.assign({}, obj1, obj2);//{a:1,b:1}吐槽ES6的扩展运算符是不是忘记了,还有数组的合并不考虑去重吗?改进const a = [1,2,3];1 k: q" {' [* L
  10. const b = [1,5,6];! n0 D9 r! x1 u/ d
  11. const c = [...new Set([...a,...b])];//[1,2,3,5,6]
    # l; [1 ]- C4 G# n( S
  12. const obj1 = {2 G4 v: b+ i( Y  P: {
  13.   a:1,* [: u3 Q, g2 R
  14. }
    : V/ b) @& F) I0 }: [# V
  15. const obj2 = {
    5 \. q4 h. r! s. b; q
  16.   b:1,
      i( a7 @: v4 r' h" I
  17. }
    2 j2 v! q- d9 Y. i2 g1 L+ N, S
  18. const obj = {...obj1,...obj2};//{a:1,b:1}
复制代码
" h; n2 [6 `* `
三、关于拼接字符串的吐槽, l3 P  r3 T' j" i$ g& M, a4 p
  1. const name = '小明';1 J% m' Z7 p: P7 T' a( G' o. i9 G3 F
  2. const score = 59;/ U) m* ?& d* H4 ^' I
  3. let result = '';" ^0 r6 \! R) u! H6 p! [* l
  4. if(score > 60){3 e* X! g, N! B) [. |: h
  5.   result = `${name}的考试成绩及格`; # E/ h5 G: T3 \5 u! K5 {
  6. }else{
    # o+ j$ f3 Q* G; C/ S
  7.   result = `${name}的考试成绩不及格`;
    % ^' c6 d0 y2 K+ \$ c% y
  8. }
复制代码

1 C) d$ J: d3 s5 u
$ z$ \. T4 V+ n6 z$ z吐槽像你们这样用ES6字符串模板,还不如不用,你们根本不清楚在${}中可以做什么操作。在${}中可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性。改进const name = '小明';9 d) W0 X; l2 y5 v; M6 R& W
  1. const score = 59;& r3 M/ D8 [3 n: i+ Q
  2. const result = `${name}${score > 60?'的考试成绩及格':'的考试成绩不及格'}`;
复制代码

5 ]; o; B) k! x, I1 m四、关于if中判断条件的吐槽if(! l5 U. s' O% g/ E$ O; c- ?
  1.     type == 1 ||( [: D# r; {) l: J6 f0 O1 O
  2.     type == 2 ||" Z! R  q, R. d+ n7 @$ W- Z4 _# K
  3.     type == 3 ||
    5 P* g9 U% w3 n# U( k" s1 u4 V
  4.     type == 4 ||# B  i) u- Z8 j9 T+ \# J/ A. x* V
  5. ){
    % v3 a1 o1 T9 I" w  z$ r6 s) D9 u
  6.    //...9 ~% L) Y. r5 e0 \' n* Q
  7. }
复制代码

7 p+ `4 L5 m9 `0 v+ v) F: v吐槽ES6中数组实例方法includes会不会使用呢?
4 c! N' i; R$ ~, @/ q( K改进const condition = [1,2,3,4];  a9 ?4 U% A6 Y: P  @
  1. if( condition.includes(type) ){
    / ~( [) a2 ~3 k, q4 y
  2.    //...! D, g  @8 T0 B" Z- H# e2 _
  3. }
复制代码
) F# M$ r0 _6 N2 q/ @0 i, v
五、关于列表搜索的吐槽在项目中,一些没分页的列表的搜索功能由前端来实现,搜索一般分为精确搜索和模糊搜索。搜索也要叫过滤,一般用filter来实现。const a = [1,2,3,4,5];" Q1 x8 C% c" ]- x. @
  1. const result = a.filter(
    8 w; c9 \" K& C8 b6 T
  2.   item =>{: n5 |% M  y( d: p
  3.     return item === 3
    1 y6 T% S; _9 F5 i9 c9 X# T5 |
  4.   }9 y' g( t/ Z4 h! [" p$ h# W2 H
  5. )
复制代码

8 k' V" P6 [; ^9 B5 F吐槽如果是精确搜索不会用ES6中的find吗?性能优化懂么,find方法中找到符合条件的项,就不会继续遍历数组。改进const a = [1,2,3,4,5];
$ B; d0 a1 j  A8 F3 k% K
  1. const result = a.find( + C9 s2 E, r- I+ W( _# O
  2.   item =>{/ \$ b; _8 [0 f; Q) H* `
  3.     return item === 32 s: r! m, i5 K: P. c" `
  4.   }
    9 b) n: p( U: l' y2 I1 u1 k" {, ]
  5. )
复制代码

( p1 d% f! v& }0 q: h7 i2 }  E2 V& M5 V) e" ~9 c/ W8 v
六、关于扁平化数组的吐槽一个部门JSON数据中,属性名是部门id,属性值是个部门成员id数组集合,现在要把有部门的成员id都提取到一个数组集合中。, @- X3 r5 g" X+ L
  1. const deps = {
    3 x2 E" }3 j; M9 I* E5 Y8 r
  2. '采购部':[1,2,3],
    / Y, V1 N4 i& a" l: P- R, l$ |. A
  3. '人事部':[5,8,12],, j$ T  F+ t: Z0 u
  4. '行政部':[5,14,79],
    , m1 H2 w- c+ |
  5. '运输部':[3,64,105],
    " E) h7 ^: y3 o: {! f
  6. }0 s; V9 k# }$ w* b# c, e
  7. let member = [];
    ' P6 O& w: |8 ^5 d3 T7 Z/ v5 n% d
  8. for (let item in deps){& j9 P; P. t9 _' B2 @/ j5 Y( b
  9.     const value = deps[item];
    1 p% o0 e" R) R
  10.     if(Array.isArray(value)){
    8 V7 q3 v0 L, @0 ]  y
  11.         member = [...member,...value]
    ) ?7 ~9 l6 A6 R* r
  12.     }
    , ]! Q, a1 _6 _1 n# r. B7 l
  13. }
    / u8 W$ S1 Z: a8 v( k
  14. member = [...new Set(member)]
复制代码

$ H: C4 Z- O% u8 z! H
# s8 T1 H6 j6 z7 a7 p) a" Y吐槽获取对象的全部属性值还要遍历吗?Object.values忘记了吗?还有涉及到数组的扁平化处理,为啥不用ES6提供的flat方法呢,还好这次的数组的深度最多只到2维,还要是遇到4维、5维深度的数组,是不是得循环嵌套循环来扁平化?0 }) [, O* L! v# g5 p! l5 W; {$ z
改进7 Z$ q+ R) f6 _: v: O
  1. const deps = {
    ( `2 l* q# P3 x$ X
  2.     '采购部':[1,2,3],1 {' R' w/ r! B4 `1 M
  3.     '人事部':[5,8,12],/ A' z1 h! G$ K2 ?
  4.     '行政部':[5,14,79],
    6 x' l  p  h6 T- y4 Y* |
  5.     '运输部':[3,64,105],& O1 U! C, M- C7 {- \
  6. }; v8 b; d$ w! W4 f
  7. let member = Object.values(deps).flat(Infinity);
复制代码
+ y2 ~- e2 }8 {; F; t6 y
其中使用Infinity作为flat的参数,使得无需知道被扁平化的数组的维度。补充flat方法不支持IE浏览器。七、关于获取对象属性值的吐槽const name = obj && obj.name;吐槽ES6中的可选链操作符会使用么?改进const name = obj?.name;八、关于添加对象属性的吐槽当给对象添加属性时,如果属性名是动态变化的,该怎么处理。let obj = {};5 e! m' i8 x( h6 f
  1. let index = 1;
    . R: w- H3 d* c
  2. let key = `topic${index}`;
    3 Z9 ~. H9 n6 l
  3. obj[key] = '话题内容';吐槽为何要额外创建一个变量。不知道ES6中的对象属性名是可以用表达式吗?改进let obj = {};, e+ u# o0 P$ [
  4. let index = 1;
    6 |$ s9 X, |6 I  {- t6 }% Q
  5. obj[`topic${index}`] = '话题内容';
复制代码

, X' `  |# L( Q% q% @' @! J6 Q0 h- h
九、关于输入框非空的判断在处理输入框相关业务时,往往会判断输入框未输入值的场景。if(value !== null && value !== undefined && value !== ''){
8 J; R+ X; \0 {1 L    //...$ V: b# b7 a" y
}
  w7 L% H' _0 q. t; _( W吐槽ES6中新出的空值合并运算符了解过吗,要写那么多条件吗?
3 I3 f1 \" ^7 f& {- rif((value??'') !== ''){2 \/ ?1 V. f% n8 C
  //.... {9 {2 Q) K2 s" D7 f# J0 I
}% U6 O8 Q3 ?" M% g; E$ S
十、关于异步函数的吐槽异步函数很常见,经常是用 Promise 来实现。: k9 R+ Z' F* l0 J% U7 w, s. y
  1. const fn1 = () =>{
    3 E* H! W/ `! s, u: m. Z  ]2 b
  2.   return new Promise((resolve, reject) => {
    4 q( z) t- N7 K% {/ t$ y
  3.     setTimeout(() => {
    9 Q0 |5 l! ~2 ?% s+ Y8 |5 ]
  4.       resolve(1);$ G7 S/ C# S+ X$ i/ @0 i$ o0 E
  5.     }, 300);
    6 l) a% s/ @5 s. l2 y: X; @* |
  6.   });
    1 K* N/ {0 p  m$ y
  7. }7 U& E  n% _: g! T8 H
  8. const fn2 = () =>{& |8 a% s) Z( _2 {+ g$ y
  9.   return new Promise((resolve, reject) => {- g! z% M, w2 t
  10.     setTimeout(() => {0 W. h3 @/ p- A( }
  11.       resolve(2);
    ; J- Z6 N4 Q. S% q, _
  12.     }, 600);4 ?2 S7 k' v$ A" M# q/ @
  13.   });
    7 q7 W' _1 K2 z4 j* ?! W- {. c* M
  14. }
    - ^/ f2 T& C8 x+ C0 T) U' L
  15. const fn = () =>{. `4 a# d; G# z  m+ d- N
  16.    fn1().then(res1 =>{
    6 R3 z# d$ o/ G. B+ x
  17.       console.log(res1);// 1$ M& ^# n5 ^0 |8 X! Y1 y
  18.       fn2().then(res2 =>{2 g. T5 x) z8 F5 B7 i
  19.         console.log(res2)
    ; c/ p! C* Y2 ^4 j
  20.       }); h* ^$ f; Z4 L0 D
  21.    })
    # |4 Y/ s& M2 q- R+ `
  22. }
复制代码
. e' ], W1 Q, I, v
吐槽如果这样调用异步函数,不怕形成地狱回调啊!改进
! H2 f2 g$ W8 K4 s' L: J
  1. const fn = async () =>{& y# g  d* ?! }7 C+ H
  2.   const res1 = await fn1();( h. G8 W; \2 K, U' l, W
  3.   const res2 = await fn2();4 s0 F) g7 t( ^1 \
  4.   console.log(res1);// 1
    , H3 j/ b8 T. s6 t* R
  5.   console.log(res2);// 2
    3 W  t  G4 Z/ _9 [8 z0 p+ n
  6. }
复制代码
$ l) y4 [/ Q2 r9 E4 ]
补充但是要做并发请求时,还是要用到
: V3 o. F; G4 k
  1. Promise.all()) t9 B4 a0 Y3 p# k# h
  2. const fn = () =>{/ Z% B/ N# P; i  z" a
  3.    Promise.all([fn1(),fn2()]).then(res =>{
    8 e2 L6 ]6 A4 d$ M) `
  4.        console.log(res);// [1,2]
    $ e5 I0 Z) U& A1 {
  5.    })
    4 O' \' E( L' |7 Z
  6. }
复制代码
  E1 m( K* i: C
如果并发请求时,只要其中一个异步函数处理完成,就返回结果,要用到Promise.race()。1 N% C. a3 z1 t! F2 c* q
十一、后续欢迎来对以上十点leader的吐槽进行反驳,你的反驳如果有道理的,下次代码评审会上,我替你反驳。此外以上的整理内容有误的地方,欢迎在原文评论中指正,万分感谢。
0 h0 @; ?. Z! c! A" W
5 y4 ]  d" V1 U: e7 r6 R; i$ g3 k( r1 x2 F7 m/ B$ U( s+ U1 l
' F8 ^1 n/ X  l$ s6 |- j, s$ [
中国领先的数字技术资源交流中心!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

5

主题

4

回帖

199

积分

学徒

积分
199
学费
176