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

cdx*_*dxf 103 javascript

alert((![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]);
Run Code Online (Sandbox Code Playgroud)

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

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

CMS*_*CMS 124

正如@Mauricio评论的那样(![]+[])[+[]]是"f"("假"的第一个字母),(![]+[])[+!+[]])是"a"等等......

它是如何工作的?

我们来看看第一个字符'f':

(![]+[])[+[]]; // 'f'
Run Code Online (Sandbox Code Playgroud)

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

![]; // false, it was truthy
!{}; // false, it was truthy
!0;  // true, it was falsey
!NaN;  // true, it was falsey
Run Code Online (Sandbox Code Playgroud)

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

false+[]; // "false"
false+''; // "false"
Run Code Online (Sandbox Code Playgroud)

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

Unary Plus操作员所做的是类型转换,Number例如:

typeof +"20"; // "number"
Run Code Online (Sandbox Code Playgroud)

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

+[]; // 0, because
+[].toString(); // 0, because
+""; // 0
Run Code Online (Sandbox Code Playgroud)

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

(![]+[])[+[]];
(false+[])[+[]];
(false+'')[+[]];
(false+'')[0];
('false')[0];  // "f"
Run Code Online (Sandbox Code Playgroud)

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

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

  • 只希望这绝不是一个面试问题. (46认同)
  • "我"来自哪里? (18认同)
  • 'underfined':D (9认同)
  • @rlemon,语言上没有`int`数据类型,实际上所有数字都是双精度64位格式(IEEE 754值),即使一些运算符在内部使用Integer值(如位运算符),结果是总是一双.这个例子中的''i'来自`undefined`,但它可能来自`Infinity`例如:`(+!+ []/+ [+ []] + [])[!+ [] + !+ [] +!+ []]`=>`(1/0 +'')[3]`=>`(无穷+'')[3]`=>`'我' (5认同)
  • @JoshStodola嗯,~3个月后,进一步澄清.在这种情况下,"i"来自"未定义",是的,但这里涉及另一个技巧.代码将"false"连接到"undefined"以形成"falseundefined"`(使用:`[![]] + [] [[]]`构造,其中"i"的索引是10.` +! + [] + [+ []]`给出"10".这用于提取"i"(如果字符串索引可以明显强制转换为整数,则可以在javascript中使用它们).产生它的最终构造是:`([![]] + [] [[]])[+!+ [] + [+ []]]` (5认同)
  • @JTA:我希望它*是*!我会通过:-D (4认同)
  • @Snoob,因为`+ []`产生零,而'0`不是真正的,因此在布尔上下文中它将产生`false`并且逻辑NOT运算符否定它:`!+ []`=>`!0` =>`!false` =>`true` (4认同)