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

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

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

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

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

x
20220429_112551_043.jpg             
$ O" `# }+ L( T' B2 I9 ?不是标题党,这是一位leader在一次代码评审会对小组成员发出的“怒吼”,原因是在代码评审中发现很多地方还是采用ES5的写法,也不是说用ES5写法不行,会有BUG,只是造成代码量增多,可读性变差而已。恰好,这位leader有代码洁癖,面对3~5年经验的成员,还写这种水平的代码,极为不满,不断对代码进行吐槽。不过对于他的吐槽,我感觉还是有很大收获的,故就把leader的吐槽记录下来,分享给掘友们,觉得有收获点个赞,有错误的或者更好的写法,非常欢迎在评论中留言。ps:ES5之后的JS语法统称ES6!!!一、关于取值的吐槽取值在程序中非常常见,比如从对象obj中取值。
  1. const obj = {) ^6 a7 F; @, m0 V4 ?. O; c, ]
  2.     a:1,; b" s* V# m4 Y# y. `& T. w/ T
  3.     b:2,
    ( d3 |4 E. i0 R% Z% c
  4.     c:3,
    0 V9 a% S9 V0 V) ?. g3 ^9 \4 t# R
  5.     d:4,) f" ^) K* }$ |7 Y  j9 i
  6.     e:5,7 A4 M& |1 d: {6 x0 o$ ?6 R) V
  7. }
复制代码

2 w3 l+ E) ~; }, s- Q* I吐槽:: e& i- f' W1 M. `( q# F. }4 Q
  1. const a = obj.a;$ B# a: f: t& j6 ^3 c' u7 s
  2. const b = obj.b;7 }% x- L  w" e
  3. const c = obj.c;6 I9 a  Z! X- g$ j5 B" g3 g5 R
  4. const d = obj.d;
    ' Z5 U) i# K! e( {
  5. const e = obj.e;
复制代码

: H; D2 k# @1 A& j1 P" h# u2 o& S* }# d
或者! f! c" _3 X! x( `% L
  1. const f = obj.a + obj.d;/ h; _! s2 A  s4 I) H9 @. G
  2. const g = obj.c + obj.e;
复制代码

1 d. Y3 }8 y$ _" F吐槽:“不会用ES6的解构赋值来取值吗?5行代码用1行代码搞定不香吗?直接用对象名加属性名去取值,要是对象名短还好,很长呢?搞得代码中到处都是这个对象名.) ^- x/ T) N' ?( L) o4 u& K
”改进:
) u! K- T, B7 M6 U
  1. const {a,b,c,d,e} = obj;
    % p3 W* r# i- m( S' P0 u9 B" T
  2. const f = a + d;8 N- R' `8 v: F6 j% F
  3. const g = c + e;
复制代码

6 v/ a: V7 U$ V1 q  E6 p反驳不是不用ES6的解构赋值,而是服务端返回的数据对象中的属性名不是我想要的,这样取值,不是还得重新创建个遍历赋值。吐槽看来你对ES6的解构赋值掌握的还是不够彻底。如果想创建的变量名和对象的属性名不一致,可以这么写:2 N1 \, N3 ?0 U* V1 z/ e( C
  1. const {a:a1} = obj;" c3 j" I0 h4 o, ?7 f2 S# n
  2. console.log(a1);// 1补充ES6的解构赋值虽然好用。但是要注意解构的对象不能为undefined、null。否则会报错,故要给被解构的对象一个默认值。, O0 ~" J4 _2 F" v3 ?7 P
  3. const {a,b,c,d,e} = obj || {};
复制代码

% D2 t8 z1 |* H二、关于合并数据的吐槽比如合并两个数组,合并两个对象。const a = [1,2,3];
2 @/ P/ h& |; E: [; `0 Y" r
  1. const b = [1,5,6];
    $ g9 I' I0 D7 T/ w; L
  2. const c = a.concat(b);//[1,2,3,1,5,6]
    * d& H+ ?8 A3 J& x
  3. const obj1 = {
    . f/ v5 T& |& b
  4.   a:1,! W' [. e2 E: ^% g& X# A; V( x
  5. }7 a& \+ H/ A1 }
  6. const obj2 = {
    8 R2 W2 ?# {$ e4 ~2 @# b% h2 u) I
  7.   b:1,
    / Z5 E' w* W: H: o* l
  8. }, D0 y& D( W" u7 ?  _' L0 p
  9. const obj = Object.assign({}, obj1, obj2);//{a:1,b:1}吐槽ES6的扩展运算符是不是忘记了,还有数组的合并不考虑去重吗?改进const a = [1,2,3];
    1 W3 N! E1 e2 {
  10. const b = [1,5,6];
    / h2 q2 t3 D+ w" F7 Z5 n4 k, {
  11. const c = [...new Set([...a,...b])];//[1,2,3,5,6], f- d* p3 T' p- G/ ?# B! m* t" @
  12. const obj1 = {
    7 Q' F/ ^2 G  k# O, |3 S( t4 L
  13.   a:1,& p. v' J5 G3 c8 F. o6 N
  14. }3 h6 L1 @; ^- d, e5 D+ O' c8 Q5 h5 P8 g
  15. const obj2 = {9 m5 j" v5 m& v+ |6 G
  16.   b:1,+ ?$ x( ~2 `& f3 I/ J; w. ]
  17. }6 @; s- u% t" U) ^, O: J; a2 t) e
  18. const obj = {...obj1,...obj2};//{a:1,b:1}
复制代码

. \3 w, J- [7 y) C  {5 `2 x6 ~5 b三、关于拼接字符串的吐槽  ~4 L: E# ]% I5 _" ]. S& N  v9 v8 ]
  1. const name = '小明';  U" h5 i: F* R
  2. const score = 59;! ]7 w" w0 f! ?
  3. let result = '';
    ' R+ X# |) o1 l
  4. if(score > 60){. s# ~+ m! e: r+ n$ [
  5.   result = `${name}的考试成绩及格`;
    ! D+ v6 n+ Y6 d8 a  B2 f7 h
  6. }else{
    & g# F( Q8 t1 E4 I1 p
  7.   result = `${name}的考试成绩不及格`;
    8 }9 n1 Z8 p2 Z" b2 z
  8. }
复制代码

2 L. B- K, q8 R8 M; L5 O& v! p2 T! |. J4 d/ f+ J
吐槽像你们这样用ES6字符串模板,还不如不用,你们根本不清楚在${}中可以做什么操作。在${}中可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性。改进const name = '小明';  b5 [& A  j) ~& f! q% F2 B3 Y
  1. const score = 59;  ?2 F( [! J" z7 U
  2. const result = `${name}${score > 60?'的考试成绩及格':'的考试成绩不及格'}`;
复制代码
% N# M! J* j; d
四、关于if中判断条件的吐槽if(
9 n9 T1 }8 T7 m" k! F: y
  1.     type == 1 ||
    ; F. i) Y1 U/ o3 H6 [
  2.     type == 2 ||
    ! |% I+ Q0 c: u+ P" D4 F$ @
  3.     type == 3 ||
    % H& i" g( u4 ]0 s: C- X% |
  4.     type == 4 ||
    4 L$ Z3 W" O1 A0 ?; d
  5. ){
    8 c# X* t0 G8 s3 A. V
  6.    //...6 R) Q# @/ g& _- M0 o8 u
  7. }
复制代码
. g7 r2 T& p  p% O
吐槽ES6中数组实例方法includes会不会使用呢?
* Y* E: N& S* P: E改进const condition = [1,2,3,4];
8 [- N0 z4 j8 S' D2 \
  1. if( condition.includes(type) ){
    # u, h2 u6 x$ ^) b! K
  2.    //...
    0 u6 ^* K& Y2 J' A8 P! x+ p
  3. }
复制代码

( E" {6 r% i5 h6 z" i/ I( P五、关于列表搜索的吐槽在项目中,一些没分页的列表的搜索功能由前端来实现,搜索一般分为精确搜索和模糊搜索。搜索也要叫过滤,一般用filter来实现。const a = [1,2,3,4,5];
4 i/ j5 v, k3 \5 L/ Z( }
  1. const result = a.filter( 7 J9 q& e8 s$ b. U: c/ y
  2.   item =>{
    ' l0 b7 m6 a# ]( ^' P: w! k
  3.     return item === 3) c# G) @! i* `0 V' |
  4.   }
    6 Z4 M9 K& H: S; X8 m3 c$ Z4 T
  5. )
复制代码

# P" }# }9 B, _; b, g* T2 I& B吐槽如果是精确搜索不会用ES6中的find吗?性能优化懂么,find方法中找到符合条件的项,就不会继续遍历数组。改进const a = [1,2,3,4,5];5 N# C6 e* i) V7 L
  1. const result = a.find(
    9 \' u( b  d  I, y% u5 Y% X
  2.   item =>{- r+ m8 q; j# q5 B0 b% J1 F+ I
  3.     return item === 34 c9 E; ^. F; R
  4.   }$ T& B8 ]8 G$ m8 K  y
  5. )
复制代码

1 g, ~/ _9 m1 t2 }4 V/ _8 u  ?0 r2 ?  g, a9 t2 m( y
六、关于扁平化数组的吐槽一个部门JSON数据中,属性名是部门id,属性值是个部门成员id数组集合,现在要把有部门的成员id都提取到一个数组集合中。( [3 j' O% y  x* x  z) f0 C
  1. const deps = {3 U5 ~. `" K, h3 v
  2. '采购部':[1,2,3],0 M/ D/ J. A8 _; _, A! I' b
  3. '人事部':[5,8,12],
    + O6 f0 A1 a. k: z; g, S; i
  4. '行政部':[5,14,79],
    $ H) a1 Y& U5 _9 V9 J; j0 V8 H8 ?' u
  5. '运输部':[3,64,105],
    8 e  v( z, o5 e, K: U6 _0 z0 o: V
  6. }
    : _* D0 Y1 i$ R( ?: v
  7. let member = [];* _0 j  m) q7 u0 L7 m* j: j
  8. for (let item in deps){2 N6 _9 F3 [& M+ g" I/ s& `" n
  9.     const value = deps[item];
    ( {& U2 j0 w9 b" X( F
  10.     if(Array.isArray(value)){) V% d- `/ k: L+ w; i- A
  11.         member = [...member,...value]. e6 |3 {4 ]- F  {  L0 ~5 [
  12.     }
    # [. I& X0 T- V' |
  13. }
    ' V( n7 X$ b+ Q7 G8 y! A
  14. member = [...new Set(member)]
复制代码
2 q) R) k/ Y2 W7 c
9 k9 a1 \# J. X6 U9 W
吐槽获取对象的全部属性值还要遍历吗?Object.values忘记了吗?还有涉及到数组的扁平化处理,为啥不用ES6提供的flat方法呢,还好这次的数组的深度最多只到2维,还要是遇到4维、5维深度的数组,是不是得循环嵌套循环来扁平化?
: X6 w; V3 k" ^/ B8 X改进
6 z  J4 t! ?" a2 c' S. Y" w
  1. const deps = {5 ]8 F+ I- B, X- n% B- p/ B& n* b
  2.     '采购部':[1,2,3],
    ! y; s* H' ]# j4 d7 c
  3.     '人事部':[5,8,12],* r2 m6 c6 |  B4 N! z( n: D
  4.     '行政部':[5,14,79],
    % m3 h9 I, d: N; Z
  5.     '运输部':[3,64,105],
    9 }: v% {/ f& E4 g, r0 Q; x
  6. }5 @$ o7 X( |" B. D1 y( P, B/ n
  7. let member = Object.values(deps).flat(Infinity);
复制代码
2 v+ d/ Q& A& e6 A9 J; ^, ]
其中使用Infinity作为flat的参数,使得无需知道被扁平化的数组的维度。补充flat方法不支持IE浏览器。七、关于获取对象属性值的吐槽const name = obj && obj.name;吐槽ES6中的可选链操作符会使用么?改进const name = obj?.name;八、关于添加对象属性的吐槽当给对象添加属性时,如果属性名是动态变化的,该怎么处理。let obj = {};
1 K+ C$ P$ U( d/ @- _3 u. V- P
  1. let index = 1;( O7 q" l; V/ p
  2. let key = `topic${index}`;4 ^1 J* y5 [# i  t
  3. obj[key] = '话题内容';吐槽为何要额外创建一个变量。不知道ES6中的对象属性名是可以用表达式吗?改进let obj = {};* C- D+ x: c& g
  4. let index = 1;
    * i' C9 U! o* K4 N/ z' ]6 X( h
  5. obj[`topic${index}`] = '话题内容';
复制代码

! r' z/ V& Z  X
7 Q! c( z2 i; v; w- Z) t8 j九、关于输入框非空的判断在处理输入框相关业务时,往往会判断输入框未输入值的场景。if(value !== null && value !== undefined && value !== ''){8 p( W$ Z" Y% s( B7 i: J
    //...) k8 F9 u% G; B" b" Q* J
}
9 r3 V) S/ p+ D3 q( t! h吐槽ES6中新出的空值合并运算符了解过吗,要写那么多条件吗?, r; p1 X) T1 G+ \* b/ S
if((value??'') !== ''){
3 I7 }/ t) @6 c/ L7 e  //...
' P% \/ @( A* t0 Q}) b& H( r7 Y; `' H) L9 J
十、关于异步函数的吐槽异步函数很常见,经常是用 Promise 来实现。
/ d. K! O4 _4 Y; K/ H5 t  f
  1. const fn1 = () =>{
    / A/ B1 {. z7 n, u* ?1 J, D6 G
  2.   return new Promise((resolve, reject) => {5 k& Y) t, V2 B0 v2 R; R2 u  `! b
  3.     setTimeout(() => {
    6 j$ i5 m" Z# J  O9 ^% ~
  4.       resolve(1);
      r% ]6 q, S/ B+ v- l
  5.     }, 300);
    # j' k6 v1 C3 }8 Q; ~
  6.   });
    ! Y8 ]$ ]/ ?  ]7 b5 N  y
  7. }2 ?! \( D7 V9 ^: c
  8. const fn2 = () =>{) ]! z4 H  Y5 h3 _2 ~4 a4 X
  9.   return new Promise((resolve, reject) => {
    - j) }) A" j' Q" x6 u% b
  10.     setTimeout(() => {$ w( M3 u7 y2 \7 w2 F0 M- j: Z/ c
  11.       resolve(2);; |6 z8 ?- D" s. `( U" s# k8 i
  12.     }, 600);) W, H9 S0 l0 \! ~0 D" B+ s: P( a# l
  13.   });% o* E3 c' s+ z# u
  14. }
    4 {+ s3 ~' {* U5 M  O0 D* @
  15. const fn = () =>{) y& R6 L+ N9 S: c) p- O# x
  16.    fn1().then(res1 =>{
    9 ~3 `9 \& H$ I' [
  17.       console.log(res1);// 1
    0 L3 R! y; ^" c% c. V' H; S7 W; ]
  18.       fn2().then(res2 =>{
    1 [" \9 K- o+ Y" b: W0 M
  19.         console.log(res2)
    + G% f( B5 Q+ d2 M
  20.       })
    * ^9 l; W* f( R# `8 [" K
  21.    })
    3 V9 T- u3 d, f# u% C7 ^2 s
  22. }
复制代码

8 Z' {3 ^. q3 P1 a吐槽如果这样调用异步函数,不怕形成地狱回调啊!改进1 c& w# x8 m" Y, @, C8 r1 a5 W/ x7 U
  1. const fn = async () =>{  b. j8 H: Q. i2 L# ?
  2.   const res1 = await fn1();. i% f1 r5 {3 r; o1 R) H
  3.   const res2 = await fn2();+ }2 f; N1 i8 a' ?
  4.   console.log(res1);// 19 \" @; ~7 f+ Y3 _
  5.   console.log(res2);// 2
    7 v5 Q5 \) c! H% J7 e
  6. }
复制代码

) [0 C0 |6 m6 n# K) `补充但是要做并发请求时,还是要用到
1 H0 [9 b4 U  M, _
  1. Promise.all()
    - @; {* a- m$ v% l
  2. const fn = () =>{$ p% o' w$ Q3 c$ }
  3.    Promise.all([fn1(),fn2()]).then(res =>{
    1 O& y$ f: @' @$ {6 m6 n' W: \
  4.        console.log(res);// [1,2]
    / b' [% @: `. P9 |+ [
  5.    }) - Z# _% V2 o  e& A8 e+ {
  6. }
复制代码

8 W! G4 R1 o& f$ G# ]9 w如果并发请求时,只要其中一个异步函数处理完成,就返回结果,要用到Promise.race()。
7 J% A, ~, r  w1 L2 G+ `十一、后续欢迎来对以上十点leader的吐槽进行反驳,你的反驳如果有道理的,下次代码评审会上,我替你反驳。此外以上的整理内容有误的地方,欢迎在原文评论中指正,万分感谢。" g4 K: X1 y) S( x+ u1 D
. [3 s8 _" Q, L

2 r* X! o) v7 t5 P# W/ V2 x' `+ \" p! C3 a! b1 R& D$ J

最近浏览会员:

  • 北极孤星
    2022-05-01
  • 商乾美工
    2022-04-29
做电商找商乾,中国最大的电商技术资源交流中心!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

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

  • 微信公众号

  • 商务合作