在浏览各个鱼塘时,遇到了一个贼nb的表达式
([][[]] + []) [+!![]] + ([] + {})[+!![] + +!![]]
而且,它不但表达式nb,它结果也很nb
哈哈哈,下面就来把这个表达式给拆分掉
从头开始,首先,[][[]],前面是个空数组,这个的意思是读取这个空数组的某个索引,但是这里面的索引是个数组,数组不能做索引,所以就会把这个数组转为字符串
所以就得到了这个[][''],读取这个空数组里面索引为空字符串的值,但是哪有这个值,所以就返回了一个undefined,所以现在就得到了这个表达式
(undefined + []) [+!![]] + ([] + {})[+!![] + +!![]]
下面我们来看这个,undefined + [],JavaScript 在某些操作符和内置函数中,处理原始类型和对象时会尝试将对象转换为原始类型,这是因为这些操作符和函数预期要处理的是原始值,而不是对象。所以这个数组要转成原始值,得到一个'',所以变成了undefined + '',得到的结果是'undefined'
在JavaScript 引擎会尝试将其解释为一个表达式,但由于括号内没有函数名或表达式,它实际上会忽略括号,并返回括号内的值,所以('undefined')得到了'undefined',所以现在的表达式是这样的
'undefined'[+!![]] + ([] + {})[+!![] + +!![]]
'undefined'[+!![]],这个又是读取'undefined'索引的值,下面我们来看这个索引 !![],任何一个东西前面加两个!,相当于是把这个东西转成布尔值,任何对象转成布尔值都是true,所以这里得到'undefined'[+true],在布尔值的前面加+作用是把布尔值转化成数字,因为true为1,false为0,所以+ture得到的结果为1,所以'undefined'[1]得到的值为'n'
需要注意的是,如果使用二元加号 +,得到的结果就不同了,比如true + true得到的结果为2,这是因为在计算时它也会进行隐式类型转换,但是转换的规则稍有不同,因为它涉及到两个操作数
所以现在就得到了这样的表达式
'n' + ([] + {})[+!![] + +!![]]
下面来看这个,[] + {},当加号两边都是非原始时怎么办,转成原始类型,空数组转为原始是'',空对象转为原始是[object Object],所以'' + [object Object]得到的结果是'[object Object]',所以就得到了这个表达式
'n' + '[object Object]'[+!![] + +!![]]
刚刚已经说过了 +!![]得到的值是1,所以得到的表达式是这样的
'n' + '[object Object]'[2]
由于'[object Object]'[2]得出来的结果是'b','n'+'b'就得到了这个表达式的结果
哈哈哈,真的很有趣
好啦,Goodbye~