上代码:
(!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]
可在任何 Javascript 环境中使用。输出方法:
console.log(
(!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]
);
上代码:
(!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]
可在任何 Javascript 环境中使用。输出方法:
console.log(
(!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]
);
10 回答11.1k 阅读
6 回答3k 阅读
5 回答4.8k 阅读✓ 已解决
4 回答3.1k 阅读✓ 已解决
2 回答2.6k 阅读✓ 已解决
4 回答2.4k 阅读✓ 已解决
3 回答2.3k 阅读✓ 已解决
刚自己在node下一句一句调了看下,其实就是各种类型的隐式转换:
我们先把上面的代码拆分为两个部分:
(!(~+[]) + {})[--[~+""][+[]] * [~+[]] + ~~! +[]]
和({} + [])[[~!+[]] \* ~+[]]
对于前面的一串代码
(!(~+[]) + {})[--[~+""][+[]] * [~+[]] + ~~! +[]]
+[]
在方括号申明的空数组前面加+号,将 Array 类型隐式转换为了 Number 类型,空数组对应的 Number 就是 0。~+[]
在 0 前面加上 ~ 号,表示按位取反,参考这里Javascript 按位取反运算符 (~),得到的结果就应该是 -1。!(~+[])
在 -1 前加 ! 号是隐式转换为 Boolean 型。-1 对应的布尔类型当然就是 false。!(~+[]) + {}
这个考察的就是,在 + 运算符的前后两个运算元都不为 Number 或 String 类型时,将自动调用两个运算元的 toString() 方法,同时转换为 String 类型进行拼接。所以此处输出false[object Undefined] // 注意,这里是字符串
(!(~+[]) + {})[/* index */]
这里便是在对之前的字符串进行取值,因为我们知道 JS 中的 String 是可以通过类似数组的方法获得某个字符的。例如var str = "Hello World"; var char = str[4]; // 数组下标以 0 开始
。那我们接下来就看看,它到底要取哪个字符。--[~+""][+[]] * [~+[]] + ~~! +[]
左边代码最终的值便是它要取的 index。那我们开始分析这段值是多少:--[~+""][+[]]
按照之前的方法,从最里面开始分析,一个 "" 表示空字符串,前面加上 + 号,是隐式转换为 Number 类型,此处转换后的值为 0,接着前面遇到一个 ~ 符号,之前有介绍,这是按位取反符号,按位取反后中括号中的~+""
值为 -1,紧接着,[-1]
则表示一个索引数组,其中有一个元素,它的值为 -1。然后[-1][+[]]
,根据上面的经验我们知道,这段代码等价于[-1][0]
,所以它最终取得该数组的第一个元素,也就是 -1。最后,-- -1
这个运算,表示在进行后面运算之前,对当前值做自减 1,所以当前代码块 结果为 -2。
换个行,缓一下。
--[~+""][+[]] * [~+[]]
此处,在后面乘了一个[~+[]]
由上面,我们可以知道,这是乘了一个[-1]
,那乘以一个数组该怎么搞呢,在这里,也是将其进行隐式转换,刚好此数组只有一个元素,那转换为 Number 便是取其第一个元素转换为 Number 类型。这小段代码最终的值便是 2。在这段代码后面,还加上了这么一段
~~!+[]
,还是根据上面的分析方法,+[]
的值为 0, ! 为强制转换为 Boolean 类型,0 转换为布尔类型便是 false, ~ 为按位取反,对于一个数字来说,两次按位取反就等于它本身。 这里~
将 Boolean 类型强制转换为 Number 类型, false 对应的 Number 类型值为 0,所以~~!0
的结果为 1 。将上面的结果做以整理可以知道,
--[~+""][+[]] * [~+[]] + ~~! +[]
的值为 3 。最终是取false[object Undefined] // 此处为字符串
的第三位字符,既为s
。(写这么多就是为了取一个 s 。。。)后面同样的分析方法,
{}+[]
则是将对象和数组转换为 String 类型进行相加, 空数组转换为 String 后为空字符串,所以上面的代码转换后值为[object Object] // 此处为字符串
后面的代码则是获得此字符串的某个字符。
[~!+[]] * ~+[]
,这一串代码的执行结果,则为需要获得的字符的下标值。[~!+[]]
的运算值为[-2] // 是一个数组
,这个数组再乘以~+[]
(运算结果为 -1),则将两个运算元隐式转换为 Number 类型,相乘结果为 2。最终,后半句代码是获得
[object Object] // 此处为字符串
这个字符串的第二位字符 b。最终输出啥,估计都知道了吧。个人感觉,这段神奇的代码是一个很好的关于 javascript 隐式类型转换的知识的例子。这也绕。。。