(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]
这种JavaScript代码是如何工作的呢,不妨来解析一下。
http://stackoverflow.com/questions/4170978/explain-why-this-works
alert((![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]);
以上代码的运行结果是alert(‘fail’); 有的人可能看到这就要说js颠覆世界观了,其实仔细看看也不是那么扯淡,主要就是灵活的类型转换和+、!运算符的一些运用。
来分步解析
(![]+[])[+[]]; // 'f'
OAO这是怎么被解析为f的?!
不要急!来看
![] // false
[]产生一个空数组,!运算符对于任何与false不严格相等的值,都返回false。在!运算符后的将会被隐式转换为boolean类型。
![]; // false, 空数组为真 !{}; // false, 空对象为真 !0; // true, 0被转换为false !NaN; // true, NaN被转换为false
然后,我们做了这样的操作:
false + [] // "false"
咦,怎么变成字符串了呢。原因在于[]这个空数组在经过转换后变成了空字符串,使用+运算符和false连接时,false将会被转换为”false”。
false.toString() //"false" [].toString() //""
这里提一下,+运算符的一些用法。+运算符可以做加法,也可以做字符串连接的工作。
当左右两个操作数都是数字或者字符串时,结果显而易见。
如果两个操作数中有一个是对象,就会调用其的toString()方法,或valueOf()方法,将其转化为字符串,然后将另一个操作数转化为字符串,进行字符串连接。如果两个字符串都不是string-like,那么则进行加法。
另外,+运算符还可以做类型转换的工作。
+ '1' // 1 + [] // 0 这里[]是一个空值,所以转换成数字的时候是0 如果转换为boolean就是false
那么这个表达式的最后一步也就出来了。完整的流程如下。
(![]+[])[+[]]; (false+[])[+[]]; (false+'')[+[]]; (false+'')[0]; ('false')[0]; // "f"
注意,用[]来访问字符串中的字符,是ECMAScript5的标准,在ES3中有charAt()函数。
其他的也就大同小异了。
参考:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
《JacaScript权威指南》第70~71页