上代码:
(!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]
可在任何 Javascript 环境中使用。输出方法:
console.log(
(!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]
);
Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
刚自己在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 隐式类型转换的知识的例子。这也绕。。。