我掌握了一些混淆的JavaScript代码。我试图理解它,并且这样做,我在控制台中输入了它的一部分。我不明白为什么为什么这个表达式在JavaScript中被评估为“a”?
> ((!!+[]+"")[+!![]])
< "a"
为什么((!!+[]+"")[+!![]])
等于"a"
在JavaScript?是否有其他代码片段来获取其他信件?
我想这是与自动铸造。
我掌握了一些混淆的JavaScript代码。我试图理解它,并且这样做,我在控制台中输入了它的一部分。我不明白为什么为什么这个表达式在JavaScript中被评估为“a”?
> ((!!+[]+"")[+!![]])
< "a"
为什么((!!+[]+"")[+!![]])
等于"a"
在JavaScript?是否有其他代码片段来获取其他信件?
我想这是与自动铸造。
((!!+[] + "") [ +!![] ])
(( !!0 + "") [ +true ])
((false + "") [ +true ])
(( "false" ) [ 1 ])
( "false"[1] )
( "a" )
有一些其他的代码片段让别人信吗?
你可以用相同的概念发挥到得到“真”,“假”,“不确定”,“南” ......
你应该运算符优先级和类型铸件工作的所有信件在JavaScript:
!!+[] // Is falsey. this is same for !!+0 or !!+""
false + "" // Is "false". as 5+"" is "5".
![] // Is falsey.
!false // Is true
+true // Is equal to 1. +[] = 0, +false = 0
而且至少,
"false"[1] // Is "a"
您是否对JavaScript中的运算符优先级有很好的参考? –
mozilla文档足够我相信。我总是在那里提及。 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table – marmeladze
让我们使用控制台来获取我们的答案假设我们不知道任何这意味着,输入
在控制台输出""
[] + ""
只是把(!!+[])
返回布尔false
。如果将布尔型false
附加到""
,则由于类型强制,您会得到字符串false
。
正如所料,打字(!!+[]+"")
输出"false"
到控制台。
在JavaScript中,您可以将字符串想像为一个字符数组,并且您可以使用数组表示法来访问它们的字符。
所以,在((!!+[]+"")[+!![]])
,你可以删除最外层的括号,使其看起来更简单。现在我们有(!!+[]+"")[+!![]]
,其中()
的第一部分返回字符串"false"
,并且[]
中的下一部分访问字符串"false"
的字符。您现在可以打赌,+!![]
莫名其妙地返回1,因为"false"[1]
等于"a"
。
现在,让我们看看如何+!![]
等于1
:
[]
是一个空数组,你能想到的作为0
这将是true
在JavaScript(因为“在JavaScript什么‘真正的’是true
”) ,所以![]是false
和!![]
是true
。
现在我们剩下的+true
这只是将true
转换为1
的数字。现在您可以看到+!![]
的评估结果为1
,并且您了解(希望)该混淆代码的工作原理!
理解这一点的关键是知道JavaScript会隐式类型转换来评估它所看到的表达式。换句话说,虽然您可能不知道向字符串添加数字意味着什么,但JavaScript会进行猜测而不是发出错误。这与你在C++中得到的结果是相反的,在这种情况下给出了明确的错误。
例如,+x
总是评估一个数字,不管是什么型号x
实际上是。 !x
同样的事情。因此,你的表达:
// A: !!+[]+"" which is evaluated like !(!(+[]))+""
+[] === 0
!0 === true
!true === false
false+'' === 'false'
// B: +!![] which is evaluated like +(!(![]))
![] === false
!false === true
+true === 1
我们得到A[B]
这简直是'false'[1] === 'a'
。
您可以在MDN了解关于implicit type conversions和operator precedence的更多信息。
隐式类型转换是经验丰富的JavaScript程序员在比较值时更喜欢使用===
而不是==
的原因。
下面是详细的一步发生了什么步骤:对数组文本操作
(!! +[] + "") [ +!![] ]
// ^^^
+[]
元加号,这相当于Number([])
导致0
。 See this为什么这个评估为0
。
(!! 0 + "") [ +!![] ]
//^^^^
!!0
相当于!!Boolean(0))
计算结果为false
因为0
是falsy值。
(false + "") [ +!![] ]
//^^^^^^^^^^^
false+""
因此简单字符串连接的计算结果为"false"
"false" [ +!![] ]
// ^^^^
!![]
相当于!!Boolean([])
和由于物体的布尔转换总是返回true。这评估为true
。
"false" [ +true ]
// ^^^^^
+true
相当于Number(true)
计算结果为1
。
"false" [ 1 ]
这是最后a
。
这里的关键是Javascript在隐式类型转换或类型强制转换时评估表达式。要了解更多关于强制类型,我建议这个优秀的资源由博士写阿克塞尔Rauschmayer先生
这整个事情可以简化为'( “假”[1])'。现在你知道为什么结果是'a'。 – abhishekkannojia
a是错误的第二个字母。聪明^^ – WayToDoor
[看这里](https://github.com/aemkei/jsfuck/blob/master/jsfuck.js) –