Javascript (![]+;[])[+;[]]。。。解释为什么这样做有效
此代码的输出为:Javascript (![]+;[])[+;[]]。。。解释为什么这样做有效,javascript,Javascript,此代码的输出为:fail。为什么? 顺便说一下,(![]+[])[+!+[]]=='false'[1],对吗?。但是为什么![]+[]==“false”以及为什么++[]==1?正如@Mauricio评论的那样,(![+[])[+[]]是“f”(假)的第一个字符,(![+[])[+!+[])是“a”,等等 它是如何工作的 让我们检查第一个字符“f”: alert((![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[
fail
。为什么?
顺便说一下,
(![]+[])[+!+[]]=='false'[1]
,对吗?。但是为什么![]+[]==“false”
以及为什么++[]==1
?正如@Mauricio评论的那样,(![+[])[+[]]
是“f”(假)的第一个字符,(![+[])[+!+[])
是“a”,等等
它是如何工作的
让我们检查第一个字符“f”:
alert((![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]);
括号之间表达式的第一部分由组成![]+[]
,加法运算符的第一个操作数是![]
,它将生成false
,因为数组对象与任何其他对象实例一样是真实的,并且应用逻辑(!)非一元运算符,它会生成值false
,例如
(![]+[])[+[]]; // 'f'
在它之后,我们有了加法的第二个操作数,一个空数组,[]
,这只是为了将false
值转换为字符串,因为空数组的字符串表示形式只是一个空字符串,相当于:
![]; // false, it was truthy
!{}; // false, it was truthy
!0; // true, it was falsey
!NaN; // true, it was falsey
最后一部分,括号后面的一对方括号,它们是属性访问器,它们接收一个表达式,该表达式由再次应用于空数组的一元加号运算符构成
一元加号运算符所做的是将类型转换为数字
,例如:
false+[]; // "false"
false+''; // "false"
再一次,这应用于空数组,正如我前面所说,数组的字符串表示形式是空字符串,当您将空字符串转换为数字时,它将转换为零:
typeof +"20"; // "number"
因此,我们可以通过以下步骤将表达式“解码”为:
+[]; // 0, because
+[].toString(); // 0, because
+""; // 0
请注意,在字符串值上使用括号表示法访问字符不是ECMAScript的一部分。版本规范(这就是charAt
方法存在的原因)
然而,这种表示字符串字符的“索引属性”在ECMAScript 5上进行了标准化,甚至在标准化之前,该功能在很多浏览器中都可用(甚至在IE8(标准模式))。正如@Mauricio评论的
(![]+[])[+[]]
是“f”(false的第一个字符),(![]+[])[+!+[])
是“a”,等等
它是如何工作的
让我们检查第一个字符“f”:
alert((![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]);
括号之间表达式的第一部分由![]+[]
组成,加法运算符的第一个操作数是![]
,它将生成false
,因为数组对象与任何其他对象实例一样是真实的,并且应用逻辑(!)例如,它不是一元运算符,而是生成值false
(![]+[])[+[]]; // 'f'
在它之后,我们有了加法的第二个操作数,一个空数组,[]
,这只是为了将false
值转换为字符串,因为空数组的字符串表示形式只是一个空字符串,相当于:
![]; // false, it was truthy
!{}; // false, it was truthy
!0; // true, it was falsey
!NaN; // true, it was falsey
最后一部分,括号后面的一对方括号,它们是属性访问器,它们接收一个表达式,该表达式由再次应用于空数组的一元加号运算符构成
一元加号运算符所做的是将类型转换为数字
,例如:
false+[]; // "false"
false+''; // "false"
再一次,这应用于空数组,正如我前面所说,数组的字符串表示形式是空字符串,当您将空字符串转换为数字时,它将转换为零:
typeof +"20"; // "number"
因此,我们可以通过以下步骤将表达式“解码”为:
+[]; // 0, because
+[].toString(); // 0, because
+""; // 0
请注意,在字符串值上使用括号表示法访问字符不是ECMAScript第三版规范的一部分(这就是存在charAt
方法的原因)
然而,这种表示字符串字符的“索引属性”在ECMAScript 5上被标准化了,甚至在标准化之前,该功能在很多浏览器中都可用(甚至在IE8(标准模式))。@Snoob我不相信你。最后,它是一个叉炸弹。当然,它是一个字符串文本;)
(![+[])[+[]]
是“f”(来自“false”的第一个字符),(![]+[])[+!+[]]]
是“a”,等等@Snoob:正如您所说,您可以在浏览器上测试每个表达式。尝试警报(![+[])
然后警报(+!+[])
你会明白的。不管是否无用,我觉得这是一个有趣的问题,我希望看到一个措辞得体的解释。如果考虑到有用性或实用性,许多代码高尔夫球场都会被关闭。练习和游戏本身就有助于扩展思维和思考过程。@Snoob我不相信你。最后,它是一个叉炸弹。当然,这是一个字符串;)(![[]+[])[+[]]
是“f”(来自“false”的第一个字符),(![]+[]])[+++[]]
是“a”,等等。@Snoob:正如你所说的,你可以在浏览器上测试每个表达式。尝试警报(![]+[])
然后警报(++[])
你会明白的。不管是否无用,我觉得这是一个有趣的问题,我希望看到一个措辞精良的解释。如果考虑到有用性或实用性,许多代码高尔夫球场将被关闭。练习和游戏本身对拓展思维和思考过程是有用的。希望这永远不是面试问题。@JTA:I hope it is!我会通过:-dw“I”来自何处?@rlemon,语言中没有int
数据类型,事实上所有数字都是双精度64位格式(IEEE 754值),即使有些运算符在内部使用整数值(如位运算符)结果总是一个双精度的。'i'
在本例中来自未定义的,但它可以来自无限
,例如:(+!+[]/++[+[]+[])[!+[]+!+[]++[]]
(1/0++][3]
(无限++][3]
=>'i'
@JoshStodola Well,~3个月后,进一步澄清。本例中的“i”来自“未定义”,是的,但还有另一个技巧