我抓住了一些混淆的JavaScript代码。我试图理解它,并且这样做,我在控制台中输入了它的一部分。我无法理解为什么
> ((!!+[]+"")[+!![]])
< "a"
为什么JavaScript中((!!+[]+"")[+!![]])
等于"a"
?是否还有其他一些代码片段可以获取其他字母?
我想这与自动投射有关。
答案 0 :(得分:7)
( ( !!+[] + "" ) [ +!![] ] )
( ( !!0 + "" ) [ +true ] )
( ( false + "" ) [ +true ] )
( ( "false" ) [ 1 ] )
( "false"[1] )
( "a" )
是否还有其他一些代码片段可以获取其他字母?
您可以使用相同的概念来获取“true”,“false”,“undefined”,“NaN”等所有字母......
答案 1 :(得分:4)
您应该在JavaScript中使用运算符优先级和类型转换:
lambda function
至少,
!!+[] // 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
答案 2 :(得分:4)
让我们使用控制台来得到我们的答案,假设我们不知道这意味着什么,输入
控制台中的 [] + ""
输出""
只需添加(!!+[])
即可返回布尔false
。如果您将布尔false
追加到""
,则会因类型强制而获得字符串false
。
正如所料,输入(!!+[]+"")
输出"false"
到控制台。
继续,在JavaScript中,您可以将字符串视为字符数组,并且可以使用数组表示法访问它们的字符。
因此,在((!!+[]+"")[+!![]])
中,您可以移除最外面的括号以使其看起来更简单。现在我们有(!!+[]+"")[+!![]]
,()
中的第一部分返回字符串"false"
,[]
中的下一部分访问字符串"false"
的字符。您现在可以打赌+!![]
以"false"[1]
等于"a"
后以某种方式返回1.
现在让我们了解+!![]
如何等于1
:
[]
是一个空数组,您可以将其视为0
在JavaScript中为true
(因为JavaScript中的“任何'真实'都是true
}“),所以![]是false
而!![]
是true
。
现在我们留下+true
,这只是将true
转换为1
的数字的简写。现在,您可以看到+!![]
如何评估1
并且您理解(希望)该混淆的代码如何工作!
答案 3 :(得分:3)
理解这一点的关键是要知道JavaScript对它看到的evalute表达式进行了隐式类型转换。换句话说,虽然您可能不知道向字符串添加数字意味着什么,但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程序员在比较值时更喜欢使用===
而不是==
的原因。
答案 4 :(得分:2)
以下详细介绍了正在发生的事情:
( !! +[] + "" ) [ +!![] ]
// ^^^
+[]
数组文字上的一元加号运算,相当于Number([])
,结果为0
。
See this为什么评估为0
。
( !! 0 + "" ) [ +!![] ]
//^^^^
!!0
相当于!!Boolean(0))
,其评估为false
,因为0
是假值。
( false + "" ) [ +!![] ]
//^^^^^^^^^^^
false+""
是简单的字符串连接,因此评估为"false"
"false" [ +!![] ]
// ^^^^
!![]
等同于!!Boolean([])
,因为对象的布尔转换返回true。评估结果为true
。
"false" [ +true ]
// ^^^^^
+true
相当于Number(true)
,其评估为1
。
"false" [ 1 ]
最后是a
。
这里的关键点是Javascript在计算表达式时进行隐式类型转换或类型强制。要了解有关类型强制的更多信息,我建议使用Axel Rauschmayer博士撰写的这篇优秀资源