[英]Why does (![]+[])[+!![]+[]] produce “a”
我有兴趣了解JavaScript的内部。 我试图阅读SpiderMonkey和Rhino的源代码,但是我的头脑很复杂。
我问的原因是:为什么会这样
(![]+[])[+!![]+[]]
产生"a"
(Å=[],[µ=!Å+Å][µ[È=++Å+Å+Å]+({}+Å)[Ç=!!Å+µ,ª=Ç[Å]+Ç[+!Å],Å]+ª])()[µ[Å]+µ[Å+Å]+Ç[È]+ª](Å)
产生alert(1)
? 资料来源: http : //sla.ckers.org/forum/read.php?24,32930,page = 1 。
在该论坛上还有更多关于JavaScript奇怪的例子,我想从编程的角度了解它在Web应用程序安全性方面的工作原理。
如果你想了解为什么那些奇怪的表达式会像他们一样工作,你可以打开firebug控制台并自己做实验。 我做了,我得到了![]
是false
, !![]
是true
,将数组添加到布尔值( false+[]
或true+[]
)会产生该值的字符串版本( false+[]="false"
)。
这样表达式归结为:
"false"["1"]
这显然是“一个”
为什么(![]+[])[+!![]+[]]
产生“a”
一步一步:这解析在: (![]+[])
和[+!![]+[]]
。 第一位已经由artemb解释: []
是一个数组。 否定它, ![]
计算为布尔值, false
- 这就是如何!
当它应用于非null
或未定义的东西时起作用。 再次如artemb所指出的那样,附加此+[]
强制将布尔值转换为字符串。 那是因为+
是字符串连接运算符。 然后将布尔值false
转换为其字符串表示形式"false"
。
然后,第二位, [+!![]+[]]
。 首先,外部[
和]
用于处理前面的字符串,我们只是将其作为一个字符数组等于"false"
。 通过在[
和]
放置一个整数索引,可以得到特定索引处的字符。 剩下的就是+!![]+[]
这包括4件: +
, !![]
, +
和[]
。 首先评估!![]
。 我们已经看到了![]
是一个布尔值false
所以先加上另一个!
否定它,并产生true
。 接下来发生的事情是+
in +!![]
被应用,并且通过应用+
它将布尔值true
转换为数字表示,即1
(所以+true
为1
)后面的+[]
产生一个字符串再次从那个1
产生"1"
但它没有真正意义,较短的表达式(![]+[])[+!![]]
已经产生a
。 追加+[]
也不会造成伤害,结果表达式只是["1"]
而不是[1]
。 我的预感是,当[]
应用于数组时, []
内的任何内容都会强制转换为数字, "1"
将再次赋予1
。 所以无论哪种方式, +!![]+[]
计算结果为1
,最终表达式为: "false"[1]
这就是说:从字符串"false"
中获取索引1处的字符,并且默认情况下为数组在javascript中从0
开始,这是"false"
的第二个字符,和a
。
为什么(![] + [])[+ !! [] + []]产生“a”
!expr
- 在expr上调用ToBoolean并翻转布尔值。 换句话说,当与not运算符一起使用时,诸如空数组之类的truthy值将产生false。 a + b
- 两个表达式都通过内部ToPrimitive运行。 如果结果值是字符串,则执行字符串连接。 否则,基元将通过ToNumber运行并添加。 对象的ToPrimitive(包含数组)将尝试toString和valueOf。 Array.prototype.toString充当没有参数的调用连接。 因此, ![] + [] = false + "" = "false"
!![] == true
,一元加运算符将表达式转换为数字,所以1
。 同样,数组转换为""
所以+!![]+[] == "1"
。 ("false")["1"] == "a"
另一种表达方式可以用类似的方式归结。 它使用unicode字符串来搞砸它并且它更长,但就像直接“解析”一样。
我建议你获取并阅读:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.