登录网站,浏览更多精彩内容
您需要 登录 才可以下载或查看,没有账号?加入我们
×
4 N4 \, a; I x- o
不是标题党,这是一位leader在一次代码评审会对小组成员发出的“怒吼”,原因是在代码评审中发现很多地方还是采用ES5的写法,也不是说用ES5写法不行,会有BUG,只是造成代码量增多,可读性变差而已。恰好,这位leader有代码洁癖,面对3~5年经验的成员,还写这种水平的代码,极为不满,不断对代码进行吐槽。不过对于他的吐槽,我感觉还是有很大收获的,故就把leader的吐槽记录下来,分享给掘友们,觉得有收获点个赞,有错误的或者更好的写法,非常欢迎在评论中留言。ps:ES5之后的JS语法统称ES6!!!一、关于取值的吐槽取值在程序中非常常见,比如从对象obj中取值。- const obj = {
. q( ?8 E7 } M( g - a:1,& w& V$ ?! `1 A3 `$ a( y5 n9 @0 @
- b:2,- i7 r, @& ^/ X& w1 {9 w
- c:3," C# ^9 A- R6 ^9 m3 u
- d:4,
0 E1 a& }* m6 F8 G3 \ |$ n7 d. C - e:5,
, S5 ?) O6 a5 a - }
复制代码
& z4 G6 u4 H: R0 T6 C* a吐槽:
# D* {- G& h I* X8 o- const a = obj.a;( n) r: z) ]1 s( I% G
- const b = obj.b;
: C& H7 ], J5 {1 o6 f' l/ D - const c = obj.c;
^. Q& f. U2 o; M$ O. N# O+ J - const d = obj.d;
+ N/ ^% o' G( ~" K( e - 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
- const f = obj.a + obj.d;
* a* Z& i$ f" `! }3 E7 r7 r - 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
- const {a,b,c,d,e} = obj;; k! b3 Z# ]9 }& n
- const f = a + d;$ h/ M* \5 S9 x. y
- const g = c + e;
复制代码
# E5 w0 V& H3 P0 T* _; E反驳不是不用ES6的解构赋值,而是服务端返回的数据对象中的属性名不是我想要的,这样取值,不是还得重新创建个遍历赋值。吐槽看来你对ES6的解构赋值掌握的还是不够彻底。如果想创建的变量名和对象的属性名不一致,可以这么写:
Q: N9 q- t) q- const {a:a1} = obj;! w- _$ s$ ~4 x# N
- console.log(a1);// 1补充ES6的解构赋值虽然好用。但是要注意解构的对象不能为undefined、null。否则会报错,故要给被解构的对象一个默认值。
$ N+ H) @, p! N( W3 K) ` - 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- const b = [1,5,6];
* u4 M. b: S, B! ]8 x1 ~. e, o - const c = a.concat(b);//[1,2,3,1,5,6] `7 f9 G* h7 @# a, t. `$ M
- const obj1 = {# n5 ^& Z0 F+ I4 r4 y
- a:1,
$ Z$ v2 z, J; P- F3 U+ D! e/ Y - } d7 S" f& o( y3 \! ~+ c3 {
- const obj2 = {+ _0 T# [6 H$ y7 Y
- b:1,# d Y* }9 a5 D' o
- }7 S) |1 q# l- {7 ^( z) k+ I4 n( ^
- const obj = Object.assign({}, obj1, obj2);//{a:1,b:1}吐槽ES6的扩展运算符是不是忘记了,还有数组的合并不考虑去重吗?改进const a = [1,2,3];1 k: q" {' [* L
- const b = [1,5,6];! n0 D9 r! x1 u/ d
- const c = [...new Set([...a,...b])];//[1,2,3,5,6]
# l; [1 ]- C4 G# n( S - const obj1 = {2 G4 v: b+ i( Y P: {
- a:1,* [: u3 Q, g2 R
- }
: V/ b) @& F) I0 }: [# V - const obj2 = {
5 \. q4 h. r! s. b; q - b:1,
i( a7 @: v4 r' h" I - }
2 j2 v! q- d9 Y. i2 g1 L+ N, S - const obj = {...obj1,...obj2};//{a:1,b:1}
复制代码 " h; n2 [6 `* `
三、关于拼接字符串的吐槽, l3 P r3 T' j" i$ g& M, a4 p
- const name = '小明';1 J% m' Z7 p: P7 T' a( G' o. i9 G3 F
- const score = 59;/ U) m* ?& d* H4 ^' I
- let result = '';" ^0 r6 \! R) u! H6 p! [* l
- if(score > 60){3 e* X! g, N! B) [. |: h
- result = `${name}的考试成绩及格`; # E/ h5 G: T3 \5 u! K5 {
- }else{
# o+ j$ f3 Q* G; C/ S - result = `${name}的考试成绩不及格`;
% ^' c6 d0 y2 K+ \$ c% y - }
复制代码
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
- const score = 59;& r3 M/ D8 [3 n: i+ Q
- const result = `${name}${score > 60?'的考试成绩及格':'的考试成绩不及格'}`;
复制代码
5 ]; o; B) k! x, I1 m四、关于if中判断条件的吐槽if(! l5 U. s' O% g/ E$ O; c- ?
- type == 1 ||( [: D# r; {) l: J6 f0 O1 O
- type == 2 ||" Z! R q, R. d+ n7 @$ W- Z4 _# K
- type == 3 ||
5 P* g9 U% w3 n# U( k" s1 u4 V - type == 4 ||# B i) u- Z8 j9 T+ \# J/ A. x* V
- ){
% v3 a1 o1 T9 I" w z$ r6 s) D9 u - //...9 ~% L) Y. r5 e0 \' n* Q
- }
复制代码
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 @
- if( condition.includes(type) ){
/ ~( [) a2 ~3 k, q4 y - //...! D, g @8 T0 B" Z- H# e2 _
- }
复制代码 ) F# M$ r0 _6 N2 q/ @0 i, v
五、关于列表搜索的吐槽在项目中,一些没分页的列表的搜索功能由前端来实现,搜索一般分为精确搜索和模糊搜索。搜索也要叫过滤,一般用filter来实现。const a = [1,2,3,4,5];" Q1 x8 C% c" ]- x. @
- const result = a.filter(
8 w; c9 \" K& C8 b6 T - item =>{: n5 |% M y( d: p
- return item === 3
1 y6 T% S; _9 F5 i9 c9 X# T5 | - }9 y' g( t/ Z4 h! [" p$ h# W2 H
- )
复制代码
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- const result = a.find( + C9 s2 E, r- I+ W( _# O
- item =>{/ \$ b; _8 [0 f; Q) H* `
- return item === 32 s: r! m, i5 K: P. c" `
- }
9 b) n: p( U: l' y2 I1 u1 k" {, ] - )
复制代码
( 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
- const deps = {
3 x2 E" }3 j; M9 I* E5 Y8 r - '采购部':[1,2,3],
/ Y, V1 N4 i& a" l: P- R, l$ |. A - '人事部':[5,8,12],, j$ T F+ t: Z0 u
- '行政部':[5,14,79],
, m1 H2 w- c+ | - '运输部':[3,64,105],
" E) h7 ^: y3 o: {! f - }0 s; V9 k# }$ w* b# c, e
- let member = [];
' P6 O& w: |8 ^5 d3 T7 Z/ v5 n% d - for (let item in deps){& j9 P; P. t9 _' B2 @/ j5 Y( b
- const value = deps[item];
1 p% o0 e" R) R - if(Array.isArray(value)){
8 V7 q3 v0 L, @0 ] y - member = [...member,...value]
) ?7 ~9 l6 A6 R* r - }
, ]! Q, a1 _6 _1 n# r. B7 l - }
/ u8 W$ S1 Z: a8 v( k - 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
- const deps = {
( `2 l* q# P3 x$ X - '采购部':[1,2,3],1 {' R' w/ r! B4 `1 M
- '人事部':[5,8,12],/ A' z1 h! G$ K2 ?
- '行政部':[5,14,79],
6 x' l p h6 T- y4 Y* | - '运输部':[3,64,105],& O1 U! C, M- C7 {- \
- }; v8 b; d$ w! W4 f
- 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
- let index = 1;
. R: w- H3 d* c - let key = `topic${index}`;
3 Z9 ~. H9 n6 l - obj[key] = '话题内容';吐槽为何要额外创建一个变量。不知道ES6中的对象属性名是可以用表达式吗?改进let obj = {};, e+ u# o0 P$ [
- let index = 1;
6 |$ s9 X, |6 I {- t6 }% Q - 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
- const fn1 = () =>{
3 E* H! W/ `! s, u: m. Z ]2 b - return new Promise((resolve, reject) => {
4 q( z) t- N7 K% {/ t$ y - setTimeout(() => {
9 Q0 |5 l! ~2 ?% s+ Y8 |5 ] - resolve(1);$ G7 S/ C# S+ X$ i/ @0 i$ o0 E
- }, 300);
6 l) a% s/ @5 s. l2 y: X; @* | - });
1 K* N/ {0 p m$ y - }7 U& E n% _: g! T8 H
- const fn2 = () =>{& |8 a% s) Z( _2 {+ g$ y
- return new Promise((resolve, reject) => {- g! z% M, w2 t
- setTimeout(() => {0 W. h3 @/ p- A( }
- resolve(2);
; J- Z6 N4 Q. S% q, _ - }, 600);4 ?2 S7 k' v$ A" M# q/ @
- });
7 q7 W' _1 K2 z4 j* ?! W- {. c* M - }
- ^/ f2 T& C8 x+ C0 T) U' L - const fn = () =>{. `4 a# d; G# z m+ d- N
- fn1().then(res1 =>{
6 R3 z# d$ o/ G. B+ x - console.log(res1);// 1$ M& ^# n5 ^0 |8 X! Y1 y
- fn2().then(res2 =>{2 g. T5 x) z8 F5 B7 i
- console.log(res2)
; c/ p! C* Y2 ^4 j - }); h* ^$ f; Z4 L0 D
- })
# |4 Y/ s& M2 q- R+ ` - }
复制代码 . e' ], W1 Q, I, v
吐槽如果这样调用异步函数,不怕形成地狱回调啊!改进
! H2 f2 g$ W8 K4 s' L: J- const fn = async () =>{& y# g d* ?! }7 C+ H
- const res1 = await fn1();( h. G8 W; \2 K, U' l, W
- const res2 = await fn2();4 s0 F) g7 t( ^1 \
- console.log(res1);// 1
, H3 j/ b8 T. s6 t* R - console.log(res2);// 2
3 W t G4 Z/ _9 [8 z0 p+ n - }
复制代码 $ l) y4 [/ Q2 r9 E4 ]
补充但是要做并发请求时,还是要用到
: V3 o. F; G4 k- Promise.all()) t9 B4 a0 Y3 p# k# h
- const fn = () =>{/ Z% B/ N# P; i z" a
- Promise.all([fn1(),fn2()]).then(res =>{
8 e2 L6 ]6 A4 d$ M) ` - console.log(res);// [1,2]
$ e5 I0 Z) U& A1 { - })
4 O' \' E( L' |7 Z - }
复制代码 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$ [
|
|