近日在 JS 项目开发中有个 array 条件判断,有人这么写:
if (list) {
// do something
}
我的 code review comment 这么建议:
if (list.length > 0) {
// do something
}
这时有另一个同事在上面留言说,按他的认知,应该是下面这么写
,也就是上面第一种才对。
if (list) {
// do something
}
这当然只是个非常非常小的问题,甚至都可以忽略不计。
但我联想到一个更有普适性的问题:当这么写代码能跑起来,另一种方式写代码也能跑。那凭什么要用另一种了?
认知
这个词可能很适合用来理解或者解释这类问题。比如这里的 认知
: 变量比较 implicit
跟 explicit
的问题。
还有一些其它的例子:
比如,自己在若干年前写代码,当时觉得自己很牛气很完美,而现在再去看,会觉得当时的代码好糟糕。
或者,当别人用 A 用法实现时,你提出用 B 用法更好,别人还得觉得自己的更好。
或者,相反的,当你觉得用 A 方式比较好时,另一个水平更高的说用 B 更好时,你还是坚持已见,觉得别人不懂你。
所有类似的问题,或许都能归结为:认知深度
的差异。这里的认知领域包括:项目工程化,模块化,团队协作,一致性,计算机编译器原理,数学,linux 内核,各种设计模式,不同编程语言各自的特色等。
这里是由一个现实案例联想到的认知问题。那么朋友们,你们有遇到过类似的场景嘛?有的话,不妨举例看看,让我们都来提高下认知吧。当然也包括,在面试或者招聘,会有人关心这类认知问题嘛?
1
luqingliang 2022-05-07 09:55:27 +08:00
空格还是 tab ?
|
2
murmur 2022-05-07 09:56:18 +08:00 20
你写的也不对啊,应该是 if list &&list.length
|
3
noe132 2022-05-07 09:58:06 +08:00 1
难道 if (list) 是正确的吗? Boolean([]) === true.
如果要判断非空当然得使用 list.length 。不过第二种写法可以改成 if (list.length),不需要判断大于 0 |
4
storyxc 2022-05-07 09:58:20 +08:00
if(conditions)后面的 { 要不要换行
|
6
luqingliang 2022-05-07 09:59:30 +08:00
这不是认知问题啊,你们这俩判断就不是一回事啊,而且就只执行到这一步判断的情况下,你的建议有报错风险
|
7
tyx1703 2022-05-07 10:02:52 +08:00 via iPhone 1
就你这个例子已经是两种语意了,改不改要看 if 里面做的事
|
8
Leviathann 2022-05-07 10:03:41 +08:00
list && list.length > 0 ?
|
9
fiypig 2022-05-07 10:03:41 +08:00
len(list)
|
10
thunderw 2022-05-07 10:09:17 +08:00 8
js 中这几个都是 false:
undefined null false 0 NaN "" 或 ''(空字符串) 而 [ ] 却是 true 。 所以归根结底你们这两种写法根本就是在判断不同的内容。所以还是要看你们这里其实是想干嘛。 |
11
f0rger 2022-05-07 10:10:00 +08:00 via iPhone 3
if(list?.length)
|
12
irobbin 2022-05-07 10:10:15 +08:00
这难道不是两种业务场景吗
如果 list 表示用户当前关注的人,list.length = 0 表示没有关注人,list = null ,表示接口数据还没返回或者出错了 |
13
ALLROBOT 2022-05-07 10:10:46 +08:00
无非是搭建玩具用孩童级别的电子积木,建造大楼就用工程化的电子积木
|
14
fstar 2022-05-07 10:11:53 +08:00
风格问题和语义化问题
- Boolean(val) 和 !!val - String(num) 和 '' + num - cb && cb() 和 if (cb) { cb() } 风格有很多种,比如经典的空格和 tab 。 不过你这个例子,感觉已经不是写法风格不同的问题了,而是代码对不对的问题。 因为空数组也是被判断为 true 的,因为它是一个不为 null 的对象。 具体得看上下文才行,其中可能有一种错误的写法。 |
15
chengyiqun 2022-05-07 10:12:30 +08:00
if (list) 这种写法, 在 list 是空 list, 但是不是 NaN 的时候, 是 true
说不定他只要判断 NaN 就行了, 不需要判断集合是否为空. 如果你要判断集合不为空 最好像上面说的 if(list && list.length) |
16
pengtdyd 2022-05-07 10:14:59 +08:00
让我想起了 rust 的哲学,既不相信程序员,也不相信机器,一切以规则为主。
|
17
oldshensheep 2022-05-07 10:18:36 +08:00 3
js 的问题,第二种要判空,要不会异常,
学 js 的时候,什么!!a ,!a 莫名其妙 Java 肯定不会那么多事了 list != null && list.isEmpty()) 只有一种写法还容易理解 fuck js |
18
yesterdaysun 2022-05-07 10:19:58 +08:00
空数组下这个 if (list)也不对吧, 我选择 if (list?.length)
顺便我也说一个应该算得上你说的这种认知问题的: Java 中很多人说不要 object.equals("test")而要"test".equals(object), 但是我一直觉得后面的写法读起来顺序很怪很反人类, 所以我宁可用 Objects.equals(obj,"test")代替, 但是其他人选择"test".equals(object) |
19
yiqunz 2022-05-07 10:21:48 +08:00
封装成工具类统一标准即可。CollectionUtils.isEmpty()
前端还有 undefined 判断 看着烦直接封装。 |
20
yiqunz 2022-05-07 10:24:20 +08:00
@yesterdaysun 这是为了避免不必要的 NPE 。不是什么教条,确实是经验所谈。
|
21
fstar 2022-05-07 10:25:03 +08:00
以前我觉得 Array.prototype.reduce 不够职责单一,也不怎么用,因为它的语义其实是 “折叠、拍平”,比如将数组的所有数字相加,拍平成一个总和值 sum 。
现在,真香。因为在我眼里,它是优雅的万能数组迭代器。 也算是自己认知成长过程中的一些变化。 下面是 tj 大神写的 node-only 方法,提取对象中的白名单属性,里面就用了 reduce: https://github.com/tj/node-only/blob/master/index.js |
22
oldshensheep 2022-05-07 10:27:49 +08:00
我上面#17 写的有点小错误,应该是不为 Empty
至于认知问题,还是对语言的理解程度问题(不不不,实际上是语言的坑人程度问题,狗头保命) |
23
codefever 2022-05-07 10:35:16 +08:00
我觉得这不是认知,这是对代码和语言的理解程度不同。
同样是为了飞翔,有人发明了飞艇,有人发明了飞机,都能飞,却是不同的科技点,越往后差距越大。 |
24
windyboy 2022-05-07 10:38:50 +08:00
是不是 review 的时候把原因描述清楚也很重要
|
25
fyxtc 2022-05-07 10:40:45 +08:00
和认知没关系,和业务和习惯有关系,一定要说的话遵循团队规范就好
|
26
belin520 2022-05-07 10:53:42 +08:00
这根本不是 code style 之间的讨论,而是边界 bug 严不严重的讨论
|
27
luffy OP 我的描述有个失误,那个例子是想表达:
``` if (list.length) { // do something } ``` 跟 ``` if (list.length > 0) { // do something } ``` |
28
devwolf 2022-05-07 10:57:38 +08:00
认知是指每行代码的理解?用意以及实际效果能否对等这样?
我的理解是 if(list) 就是简化的 if(!!list) ,是判断 list 是否转布尔后为 true 。 而 if(list.length>0) 则是 list 中的 length 属性是否大于 0 隐患是 list 可能 undefined ,所以优化+简化写法是 if(list?.length) if 后面本身有布尔转换了,length 有 0 就会走 else 的逻辑,然后用 可选链操作符?. 进行 list 是否 undefined 的效验拦截 ——个人理解 |
29
babyoung 2022-05-07 10:59:20 +08:00
那为什么不用 .isArray 呢?
因为比较长吗? |
30
devwolf 2022-05-07 11:01:14 +08:00
#28 补充:
哦,看到楼主#27 的补充描述了。 如果是对比 if( list.length ) 和 if( list.lenght > 0 )的话,后者提高了可读性吧,前者写起来快。我也认为是小问题 |
31
IvanLi127 2022-05-07 11:08:41 +08:00
你的 review 结果不对啊,如果原代码是判断是否是数组,不得 ``Array.isArray(list)``,如果确定是数组或是 falsy 的话,那直接 ``!!list`` 或者 ``list`` 也没啥问题。判断 length 是无法确保这货是不是数组。如果判断非空的话,原代码也做不到呀。。。
|
32
fsworld 2022-05-07 11:13:53 +08:00
什么是好代码:
1 、可读的:逻辑清晰,bug 难以隐藏 2 、可发布的:统一的异常处理,必要的性能优化,各种情况都有考虑到,健壮性好 3 、可维护的:避免重复,合理的模块划分,易于修改,便于扩展 看法: 1 、代码始终是写给人看的 2 、团队协作,采用大家都在遵守的规范 3 、不断学习,提高自己的认知和见识,知之为知之,不知为不知 tips:另如果不能保证判断的变量是一个数组,如接口返回 null 值,建议: ``` if (Array.isArray(arr) && arr.length) { // do something } ``` 更建议封装单独的方法,并对其进行单元测试: ``` const isNotEmptyArray = arr => Array.isArray(arr) && arr.length ``` |
33
luffy OP 不好意思,因为正文描述中的失误,导致一开始的讨论都聚集在了 边界条件 判断上了。
具体看 #27 补充说明。 我这里的例子更多是想表达,有人觉得用默认让计算机 自动做隐式转换成 boolean 就可以,而我给的 comment 是,显示用 boolean 做判断。 然后以此抛砖引议,想看下各位有遇到其它情况之类的。 |
34
jjwjiang 2022-05-07 11:15:26 +08:00 1
第一,你的主题里描述的是完全不等价的判断,而你在#27 的补充里说这是你的失误,你想表达的是 length 和 length>0 ,但是这个概念过于基础我觉得已经深入了对 JS 稍有了解的开发者心中,所以我怀疑你自己可能一开始就没搞明白这其中的区别。
第二,.length 和.length>0 在 JS 里就是完全等价的,前者也是非常常规的写法,没有意义也没有必要去讨论这个点 |
35
Kenmin 2022-05-07 11:18:58 +08:00
看最新的楼主描述,如果只是检测 Array 非空,我更倾向于第一种写法,第二种太 Java 了
原先的条件判断在 js 里语义完全不同 |
39
duduaba 2022-05-07 11:24:39 +08:00
写多了代码就会改变认知:不是自己负责的项目临时参与的话,只写自己的代码,千万别手贱去东别人的代码,尽管觉得丑陋可能出 bug ,你可以说没责任心。但是这种是最基本的『协作』
|
40
zyxyz123 2022-05-07 11:25:26 +08:00
.length 和 .length > 0 都行,就是后者的可读性更强
|
41
meeop 2022-05-07 11:26:39 +08:00
我说一个毛主席的做法吧:
1 这个问题不在于对错,而在于拉齐认知,具体来说就是定一个规范,说明这种情况大家应该怎么写 |
42
meeop 2022-05-07 11:26:53 +08:00
2 拉齐认知的方法,是开民_主生活会,具体来说就是通过全员讨论方式讨论这个问题的解决方法并投票达成一致,形成决定
|
43
meeop 2022-05-07 11:27:06 +08:00
3 显然上述方法挺麻烦,以及个人经验大部分人没这么强民_主意识,会觉得小题大做,搞不搞看成本和意愿
|
44
meeop 2022-05-07 11:27:51 +08:00
民_主是敏感词,发了 3 次才发出来
|
45
krixaar 2022-05-07 11:31:40 +08:00
@pianjiao #36 360 安全浏览器 12 的 Chrome 内核是 78 ,内网某个网页版系统升级了,然后挂掉一批电脑,我拿着 U 盘跑过去给装 13 。为什么不用别的浏览器?因为这个内网系统是个大 SPA ,把以前只能用 IE 的老系统(带 ActiveX 控件的)也给包进去了,只有两个内核随便切的浏览器才能用。
当时控制台 js 一片报错,原因就是新版某个 js 里面有个.?…… |
46
simonh8 2022-05-07 11:42:40 +08:00
想不通 js 这么🌶️的语言怎么能流行起来
|
47
nicebird 2022-05-07 11:55:46 +08:00
对都对。但是从清晰的角度看,length 版本更好,非 length 的写法需要脑补一小段才能理解,提升了认知成本。代码其实阅读的时间是最多的,降低阅读认知成本的事情要多做。
|
48
RuiQ 2022-05-07 12:37:39 +08:00 1
除非对方比你高很多 level ,能让你直白的感受到他是大牛。
否则在大家都差不多的情况下,程序员之间也颇有文人相轻的意味。 |
49
CosimoZi 2022-05-07 12:55:24 +08:00
在幺半群里作为零元的元素本来就该映射到 false 上. js 设计问题. python 就做得很好.
|
50
DrakeXiang 2022-05-07 12:58:53 +08:00
对于 `if (list.length)` 还是 `if (list.length > 0)` 我主要还是看可读性,虽然我好像两种都用过,而且印象中偏向第一种,但我觉得第二种的可读性更好,只是感觉现在写成第一种基本也能看懂了。
其他还有一些比较骚的类型转换,比如 `!!name`, `+new Date()`, `~~floatNum` 这种,在刚学的时候用过,后面看了一些文章说到可读性,现在几乎不用了,而是用 `Boolean(name)`, `Number(strNum)`, `Math.floor(floatNum)` 这种显式的转换 |
51
charlie21 2022-05-07 13:42:14 +08:00
从成品揣测需求是一种浪费生命的方式
|
52
pianjiao 2022-05-07 13:57:17 +08:00
@krixaar 如果要兼容老的浏览器,我觉得 list && list.length > 0 这种比较好,其实 单 list 也是可以的 反而 list.length 在 list 是个 undefined 或者 null 的时候无法兼容 直接报错
|
53
wjccccccccc 2022-05-07 14:15:10 +08:00 1
@meeop 看到你这绷不住了,不能说的"民""主"
|
54
Agdhfdjh 2022-05-07 14:22:11 +08:00
if (!!list?.length) ...
有 webpack 可以用可选链语法,js 这种灵活的语言,没有绝对的规范,就是灵活和严谨中取一个度,很多写法都是为了代码可读性考虑的,比如有些公司强制使用 Number(var) 取代 +var |
55
dongtingyue 2022-05-07 14:31:09 +08:00
看了补充,我选择( xx.length) 而不会写( xx.length>0),首先 length 肯定是>=0 没必要在写>0 。代码评审不应该关注这种点吧,是有多闲,然道 if(bool) 还要写 if(bool==true)?
|
56
unclemcz 2022-05-07 14:44:12 +08:00 via Android
@simonh8 #46 你们这些专业程序员理解不了我们这种半吊子,不考虑类型瞎写的 js 代码不会报错还能正常运行,多么的快乐。我们业余选手反正只写一些代码段简化日常重复工作,不需要工程化思维,js 这种弱类型功能又强大的语言,简直不要太友好🙂。
|
57
tao1991123 2022-05-07 15:04:34 +08:00
其实应该是 if(Array.isArray(list) && list.length) { }
|
58
jujusama 2022-05-07 15:33:43 +08:00
非 js coder ,看到示例时满脑子都是按语境转换和数据类型向下转换导致的警告
|
59
Tokin 2022-05-07 17:13:49 +08:00
一般是 if(list && list.length) 或者 if( ( list || [] ).length )
|
60
kingjpa 2022-05-07 17:41:30 +08:00
小程序里 空数组也是 true
|
61
keithwhisper 2022-05-07 18:03:34 +08:00
应该是
```js if (Array.isArray(list) { // do sth. } ``` |
62
keithwhisper 2022-05-07 18:05:09 +08:00
其实加上了 `list.length` 的判断反而不好读了, 对空数组做一次处理也没什么问题
|
63
keithwhisper 2022-05-07 18:10:48 +08:00
另外用 `length` 判断的话, 会有 array-like 的数据通过校验
|
64
simonlu9 2022-05-07 18:17:41 +08:00
我来说下 java 怎么处理这种,假如你代码确定这个类型是集合的话一般会用 CollectionUtils.isEmpty 方法,如果是字符串的话就用 StringUtils.isEmpty, 其他类型就是 Option.ofNullable(T) 来处理但是 js 是动态语言,没法判断,只能你根据行为来判断比较好,建议项目中封装这几个判断,减少太多的判空重复代码
|
65
chiling 2022-05-07 19:46:15 +08:00
1. 如果是长期维护的中大型项目,上 Typescript ,因为相对强类型,所以能解决掉一部分楼主所说的代码问题
2. 在实际业务团队协作中确实会遇到一些代码风格、书写方式的问题 举一些例子: - 对象属性的 merge Object.assign(oldObj, newObj) 和 { ...oldObj, ...newObj } - 数组的 merge:const newArr = oldArr.concat(arr) 和 const newArr = [...oldArr, ...arr]; - 属性判空操作 obj.fun && obj.fun() 和 obj?.fun() - .... 我个人感觉合适的解决方式:1. 建立团队的代码规范 2. 给项目代码加上 eslint 3. 写法的好坏我感觉主要看适配业务场景谁更好一点,写法上谁更优雅易读一点,前端之前几年发展很快,一些可能的优雅写法可能又有了更优雅的写法,加上自己的认知在变化,觉得之前写的代码糟糕可能是正常的 4. 我的写法倾向于 if (list?.length > 0) { } |
66
lucays 2022-05-07 22:02:45 +08:00
单说 python 里,都是用第一种的,if obj: xx ,这个 obj 不管是 None(null)还是[]还是''还是{}还是什么乱七八糟的都过不了
|
67
songkeys 2022-05-08 01:41:22 +08:00 2
看到楼主的附言:
> 这个只是做为一个举例引用,没想到反而成为大家的焦点。 > 这是我事先没有预料到的,这个贴子的回复已经背离我的初衷,因为我本想通过举个例子来看下其它人在其它领域的遇到的情况,但没想到所有人都纠住这个例子不放。 > > 如果是这样,此贴可以关闭了,后面如果再对这个例子进行讨论的话,就真的没意思了,真的意义不大。 > 有时间应该放在更重要的事情上,真的没必要再往这个例子再多做说明了。 实在槽点满满。你的举例犯了这种低级错误,当然会让人摸不着头脑,讨论开来。怎么反而责怪大家讨论这个的对错呢?另外,帖子已经发出来了,人们作出如何回复自然是无法百分百遵循发帖人的「意愿」的,说出「这个贴子的回复已经背离我的初衷」这种冲浪新手才会说的丧气话可谓是二度让人摸不着头脑。 我非常同意「有时间应该放在更重要的事情上」,但建议楼主下次发帖前仔细审审有无纰漏,不要疑惑了大家后,望着一片狼藉的讨论,等了二十多楼后再站出来一边纠正错误一边感慨这届网友水平不行实在带不动,然后拂袖离去,深藏功与名。这样才是真的浪费了大家的时间。 |