(! + )] …解释为什么这个工作
alert((![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]);
此代码的输出是: fail
。 为什么?
顺便说一句, (![]+[])[+!+[]] == 'false'[1]
,对吗? 但为什么![]+[] == "false"
,为什么+!+[] == 1
?
作为@Mauricio评论(![]+[])[+[]]
是“f”(“false”的第一个字符), (![]+[])[+!+[]])
是“a “等等…
它是如何工作的?
我们来看一下第一个字符'f':
(![]+[])[+[]]; // 'f'
括号之间的expression式的第一部分由![]+[]
,加法运算符的第一个操作数是![]
,因为数组对象(与任何其他对象实例一样)是truthy ,并应用Logical(!)NOT一元运算符,例如,它会生成值false
。
![]; // false, it was truthy !{}; // false, it was truthy !0; // true, it was falsey !NaN; // true, it was falsey
之后,我们有第二个操作数的加法,一个空的数组, []
,这是为了将false
值转换为String,因为空数组的string表示forms只是一个空string,相当于:
false+[]; // "false" false+''; // "false"
最后一部分是括号后面的方括号,它们是属性访问器,它们接收一个由一元加运算符再次应用于一个空数组的formsexpression式。
Unary Plus运算符的function是将Number
转换为Number
,例如:
typeof +"20"; // "number"
再次,这是应用于一个空的数组,如前所述,一个数组的string表示forms是一个空string,当您将一个空string转换为数字时,它将转换为零:
+[]; // 0, because +[].toString(); // 0, because +""; // 0
因此,我们可以在一些步骤中“解码”expression式:
(![]+[])[+[]]; (false+[])[+[]]; (false+'')[+[]]; (false+'')[0]; ('false')[0]; // "f"
请注意,通过在string值上使用括号表示来访问字符不是ECMAScript 3rd的一部分。 版规范,(这就是为什么charAt
方法存在)。
然而,这种代表string字符的“索引属性”在ECMAScript 5中是标准化的,即使在标准化之前,该function在许多浏览器(即使在IE8(标准模式))中也是可用的。