【发布时间】:2013-05-26 21:41:17
【问题描述】:
我最近从某个来源看到了一个表达式,如下所示 -
++[[]][+[]]+[+[]]
将其输入 Chrome(Windows 7,版本 27.0.1453.94 m)控制台会显示 "10" 的结果。
有人能解释一下这里发生了什么吗?
【问题讨论】:
标签: javascript expression
我最近从某个来源看到了一个表达式,如下所示 -
++[[]][+[]]+[+[]]
将其输入 Chrome(Windows 7,版本 27.0.1453.94 m)控制台会显示 "10" 的结果。
有人能解释一下这里发生了什么吗?
【问题讨论】:
标签: javascript expression
此表达式将有效的 Javascript 构造字符串化,产生 NaN、数字、布尔值 undefined 等。
例如
+[] -> 0 //The unary plus operator is applied to the result of toString applied to an empty array (which is an empty string)
!+[] -> true
你也可以看看this question, 并在no alnum cheat sheets。
【讨论】:
++[[]][0]+[0],只是无法弄清楚1 是如何出现在这里的......
++[[]][+[]] 列为等同于1,但没有给出任何解释......
+[]是从数组到数字0的数字转换。
而+[0] 也是 0。
所以最终结果可以推导出为(++0) + [0],即1+[0]。
对于一个数字添加一个数组。它们被转换为字符串,因此结果实际上是 '10'。
您可以登录typeof(++[[]][+[]]+[+[]])进行验证。
【讨论】:
JavaScript 在数据类型之间的转换方面相当灵活。首先要注意的是 +[] 的计算结果为 0。* 这让我们可以将表达式重写为:
++[[]][0] + [0]
接下来要注意的是++[[]][0] 是应用于[[]] 的第一个元素的预增量运算符。通常你不能将++ 应用于数组,但是 JavaScript 友好地将第一个元素转换为0,所以结果是++[[]][0] 计算为1([[]] 的第一个元素现在已经递增)。有点像这样:
var a = [[]];
var b = ++a[0];
// now a will be [1] and b will be 1
这给我们留下了:
1 + [0]
JavaScript 现在将 int 和数组转换为字符串(因为 [0] 不是数值)并将它们连接在一起。完成!
* 我对+[]如何变成0的理解是,这是一个两步的过程:首先,[]被转换成一个字符串原语,也就是空字符串。然后,空字符串转换为一个数字,该数字为零。通过相同的路径,[1] 计算结果为 '1',然后计算结果为 1,[2] 计算结果为 2,等等。但是,[1, 2] 计算结果为 '1,2',其计算结果为 NaN。 (最后因为小数点分隔符是.,而不是,。我不知道如果我的语言环境不同会发生什么。)
【讨论】:
[[]][0] 转换为0 部分。在这个过程中遵循哪个转换规则?
++ 不能应用于数组,但它可以应用于数组元素。 [[]]的第一个元素是[];尝试将++ 应用于触发JS 将[] 转换为0(就像它对+[] 所做的那样)。
++Expr 通过评估ToNumber(GetValue(Expr)) 开始(经过一些错误检查)。 §9.3 指定对象参数的ToNumber 从评估ToPrimitive(value, Number) 开始。反过来,(根据 §9.1)调用对象的 [[DefaultValue]] 内部方法。 §8.12.8 描述了当提示类型为数字时[[DefaultValue]] 如何为对象工作。那里指定的过程基本上就是我所描述的:转换为字符串(在第一次尝试使用valueOf() 转换为原语失败后)然后将其解析为数字(根据第 9.3 节)。