我昨天看到这个非常有趣的screencast关于Ruby和Javascript等语言中的一些奇怪的东西,这个人表明:
[] + [] -> "" // returns empty string
不是很明显......
我决定转到ECMAscript language specification获取更多信息。我开始使用+
运算符实现(第75页),其中说:
11.6.1加法运算符(+)
加法运算符执行字符串连接或数字加法 生产AdditiveExpression:AdditiveExpression + MultiplicativeExpression的计算方法如下:
1.让lref成为评估AdditiveExpression的结果 2.让lval为GetValue(lref) 3.让rref成为评估MultiplicativeExpression的结果 4.让rval为GetValue(rref)。
5.让lprim为ToPrimitive(lval)。
6.让rprim为ToPrimitive(rval)。
7.如果Type(lprim)是String或Type(rprim)是String,那么
一个。返回串联ToString(lprim)后跟ToString(rprim)的结果的字符串
8.将添加操作的结果返回到ToNumber(lprim)和ToNumber(rprim)。见11.6.3下面的注释。注1:在步骤5和6中对ToPrimitive的调用中没有提供提示。除Date对象之外的所有本机ECMAScript对象都处理没有提示,就像提供了提示号一样;日期对象处理缺少提示,就像提供了提示字符串一样。主机对象可以以某种其他方式处理缺少提示。
注2:步骤7与关系运算符(11.8.5)的比较算法的步骤3的不同之处在于,使用逻辑运算而不是逻辑运算。
我的猜测是,通过不同的评估/转换以某种方式达到了第7点,但我无法弄清楚究竟发生了什么......
有人能为此提供一个直截了当的解释吗?
为了尝试回答原因,我愿意更好地理解这一切:
[] + {} -> [object Object]
{} + [] -> 0
答案 0 :(得分:7)
- 让lprim为ToPrimitive(lval)。
- 让rprim为ToPrimitive(rval)。
醇>
由于没有向ToPrimitive
提供提示:
当调用O的[[DefaultValue]]内部方法时没有 提示,然后它的行为就好像提示是数字,除非O是一个日期 对象(见15.9.6),在这种情况下,它的行为就像提示一样 字符串。
所以它与使用数字提示调用相同:
When the [[DefaultValue]] internal method of O is called with hint Number, the following steps are taken:
1. Let valueOf be the result of calling the [[Get]] internal method of object O with argument "valueOf".
2. If IsCallable(valueOf) is true then, a. Let val be the result of calling the [[Call]] internal method of valueOf, with O as the this value and an empty argument list. b. If val is a primitive value, return val.
3. Let toString be the result of calling the [[Get]] internal method of object O with argument "toString".
4. If IsCallable(toString) is true then, a. Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list. b. If str is a primitive value, return str.
5. Throw a TypeError exception.
由于[].valueOf()
的返回值不是原始值,因此会转到[].toString()
,返回""
。
这同样适用于对象对象,除了对象的.toString
返回[object Object]
,而数组的.toString
返回.join(",")
{} + []
此处{}
不被视为对象,而是作为空块。所以运行的代码是:
{}
+[]; //Same as +[] ( Number([]) ) which is 0
解决歧义并从{} + []
使用
({}) + []
或({} + [])
有趣的代码:
{} ! [] //false
({}) ! [] //SyntaxError