a+b:动态类型是灾难之源还是最好的特性?(下)
上一篇,我们说到如何将复杂的类型转换缩减到两条简单的规则,以及两种主要类型。这两条简单规则是:
1.从值 x 到引用:调用 Object(x) 函数。
2.从引用 x 到值:调用 x.valueOf() 方法;或,调用四种值类型的包装类函数,例如Number(x),或者 String(x) 等等。
两种主要类型则是字符串和数字值。
当类型转换系统被缩减成这样之后,有些问题就变得好解释了,但也确实有些问题变得更加难解。例如 graybernhardt 在讲演中提出的灵魂发问,就是:如果将数组跟对象相加,会发生什么?
如果你忘了,那么我们就一起来回顾一下这四个直击你灵魂深处的示例:
> [] + {}
'[object Object]'
> {} + []
0
> {} + {}
NaN
> [] + []
''
而这个问题,也就是这两讲的标题中“a + b”这个表达式的由来。也就是说,如何准确地解释“两个操作数相加”,与如何全面理解 JavaScript 的类型系统的转换规则,关系匪浅!
转换过程
一般来说,运算符很容易知道操作数的类型,例如“a - b”中的减号,我们一看就知道意图,是两个数值求差,所以 a 和 b 都应该是数值;又例如“obj.x”中的点号,我们一看也知道,是取对象 obj 的属性名字符串 x。
当需要引擎“推断目的”时,JavaScript 设定推断结果必然是三种基础值(boolean、number 和 string)。由于其中的 boolean 是通过查表来进行的,所以就只剩下了number 和 string 类型需要“自动地、隐式地转换”。
但是在 JavaScript 中,“加号(+)”是一个非常特别的运算符。像上面那样简单的判断,在加号(+)上面就不行,因为它在 JavaScript 中既可能是字符串连结,也可能是数值求和。另外还