(![] + [])[+ []] ...解释为什么会这样

时间:2010-11-13 04:29:54

标签: javascript

alert((![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]);

此代码的输出为:fail。为什么?

顺便说一下,(![]+[])[+!+[]] == 'false'[1],对吗?但为什么![]+[] == "false"和为什么+!+[] == 1

1 个答案:

答案 0 :(得分:120)

由于@Mauricio评论(![]+[])[+[]]是“f”(“假”的第一个字母),(![]+[])[+!+[]])是“a”等等......

它是如何运作的?

让我们检查第一个字符'f':

(![]+[])[+[]]; // 'f'

表达式的第一部分 - 在括号之间 - 由![]+[]组成,加法运算符的第一个操作数是![],它将产生false,因为数组对象 - 与任何其他Object实例一样, truthy ,并应用Logical(!)NOT一元运算符,例如,它会生成值false

![]; // false, it was truthy
!{}; // false, it was truthy
!0;  // true, it was falsey
!NaN;  // true, it was falsey

之后,我们有了第二个操作数,一个空数组,[],这只是为了将false值转换为String,因为空数组的字符串表示形式是只是一个空字符串,相当于:

false+[]; // "false"
false+''; // "false"

最后一部分,括号后面的方括号,它们是属性访问器,它们接收一个表达式,由一元数运算符再次应用于空数组形成。

Unary Plus运算符所做的是类型转换,到Number,例如:

typeof +"20"; // "number"

再一次,这应用于一个空数组,正如我之前所说,数组的String表示形式是一个空字符串,当你将一个空字符串转换为Number时,它被转换为零:

+[]; // 0, because
+[].toString(); // 0, because
+""; // 0

因此,我们可以在某些步骤中“解码”表达式:

(![]+[])[+[]];
(false+[])[+[]];
(false+'')[+[]];
(false+'')[0];
('false')[0];  // "f"

请注意,在String值上使用括号表示法访问字符不是ECMAScript 3rd的一部分。版本规范,(这就是charAt方法存在的原因)。

然而,这种代表字符串字符的“索引属性”在ECMAScript 5上标准化,甚至在标准化之前,该功能在很多浏览器中都可用(即使在IE8(标准模式)中)。 / p>