抛出一个问题
昨天我的群里有人问了这样一个问题:
+[1] // 1 +[1,2] // NaN // 提问:为什么第一个返回 1,第二个返回 NaN 呢?
这是一个很小的问题,但是我本能的反感,一看就是无聊到极致的面试官问出来的,如果是我就会反问:
- 什么场景下会出现这种问题?
- 如果真有这种场景要写这样的代码,你有没有考虑后续维护的问题?
但是作为一个温柔的小群主,我还是要去解答这个问题,但是我同时更想通过问题去提升提问者解决问题的能力,因为:
- 问题是层出不穷的,而解决问题的能力是贯穿整个职业生涯的
于是就有了这篇文章,带着大家从看到问题到寻找权威的解释去对问题进行解答与探索,毕竟授人以鱼,不如授人以渔。
寻觅答案之旅
我们可以先将问题做一个转换:
Number([1]) // 1 Number([1,2]) // NaN
即:为什么数组 [1] 转为 Number 类型是 1,而数组 [1,2] 转为 Number 类型是 NaN。
这时我们可以前往 ECMA 的官网去寻找答案,众所周知 ECMAScript 语言规范所对应的是 ECMA-262:
www.ecma-international.org/publication…
根据网页中的指引,我们可以寻找到 ecma262 标准的文档:
对于上面的一些专有词汇进行简要解释:
- ECMA:ECMA国际组织,全称是Ecma International (以前叫 ECMA - European Computer Manufacturers Association - 欧洲计算机制造商协会)是个行业标准组织,它所通过的标准都是 ECMA-nnn 这样进行编号。
- tc39:是ECMA 国际组织第 39 号技术委员会( Technical Committee ),它是一个推动 JavaScript 发展的委员会。TC39 由各个主流浏览器厂商的代表构成,他们的主要工作就是制定 ECMAScript 标准,标准生成的流程,并实现。
进入到页面,我们第一步当然是找到 Number:
这时我们发现,Number
作为方法调用的时候我们会执行 ToNumeric(value
) 方法:
这个方法会先去执行 ToPrimitive(value
, number) 方法:
这个方法很长,也比较难去阅读,但是我们可以精准的发现,他无非是一个寻找转换类型 preferredType
的过程,在这个问题里,我们这个类型就是 number
,最后我们拿着这个东西去执行 OrdinaryToPrimitive(input
, preferredType
),我们似乎是看到曙光了:
这个方法会判断我们之前的 preferredType
,因为我们这个类型是 number
,所以 我们会先后执行 "valueOf
", "toString
",注意文档中的这句类代码:
If Type(result
) is not Object, return result
.
我们先执行了 valueOf
,如果返回值是个对象,我们才去执行 toString
,然而,数组执行 valueOf
返回的是本身,所以这个方法最后返回的是 [xxx].toString()
而数组的 toString
会返回什么呢?,我们继续搜:
看到这里我们就不需要继续往下看了,很显然会执行数组的 join
方法,而 join
默认是由 ','
进行拼接的:
而这个问题就很简单的转换为了:
Number('1') // 1 Number('1,2') // NaN
这样答案就显而易见了🌟
我们这次探索的目标也就达成了
解决问题是一种能力
其实我们做一个程序员,经常会遇到各种问题,但是遇到问题,我们可以通过自己的方法找到更加权威的解答一定是我们向上成长的关键能力。