js带你颠覆世界观

(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]

这种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页

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注