为什么Array + Array等于空字符串?

时间:2012-01-21 08:32:22

标签: javascript

我昨天看到这个非常有趣的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

1 个答案:

答案 0 :(得分:7)

  
      
  1. 让lprim为ToPrimitive(lval)。
  2.   
  3. 让rprim为ToPrimitive(rval)。
  4.   

由于没有向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