2017-05-28 351 views
6

我掌握了一些混淆的JavaScript代码。我试图理解它,并且这样做,我在控制台中输入了它的一部分。我不明白为什么为什么这个表达式在JavaScript中被评估为“a”?

> ((!!+[]+"")[+!![]]) 
< "a" 

为什么((!!+[]+"")[+!![]])等于"a"在JavaScript?是否有其他代码片段来获取其他信件?

我想这是与自动铸造。

+4

这整个事情可以简化为'( “假”[1])'。现在你知道为什么结果是'a'。 – abhishekkannojia

+0

a是错误的第二个字母。聪明^^ – WayToDoor

+2

[看这里](https://github.com/aemkei/jsfuck/blob/master/jsfuck.js) –

回答

6
((!!+[] + "") [ +!![] ]) 
(( !!0 + "") [ +true ]) 
((false + "") [ +true ]) 
(( "false" ) [ 1 ]) 
(  "false"[1]  ) 
(   "a"   ) 

有一些其他的代码片段让别人信吗?

你可以用相同的概念发挥到得到“真”,“假”,“不确定”,“南” ......

+1

这是正确的答案。 – SVSchmidt

+1

为什么'+ []'等于0?猜猜它将空数组转换为数字,所以,为什么不是0 ...但值得我认为小线......并且如果可能,我的猜测会更好:) –

+0

@HuguesMoreau单元加操作'+'解析'[[ ]'为数字类型 – pomber

4

你应该运算符优先级和类型铸件工作的所有信件在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" 
+2

您是否对JavaScript中的运算符优先级有很好的参考? –

+0

mozilla文档足够我相信。我总是在那里提及。 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table – marmeladze

4

让我们使用控制台来获取我们的答案假设我们不知道任何这意味着,输入

在控制台输出""

[] + ""只是把(!!+[])返回布尔false。如果将布尔型false附加到"",则由于类型强制,您会得到字符串false

正如所料,打字(!!+[]+"")输出"false"到控制台。

在JavaScript中,您可以将字符串想像为一个字符数组,并且您可以使用数组表示法来访问它们的字符。

所以,在((!!+[]+"")[+!![]]),你可以删除最外层的括号,使其看起来更简单。现在我们有(!!+[]+"")[+!![]],其中()的第一部分返回字符串"false",并且[]中的下一部分访问字符串"false"的字符。您现在可以打赌,+!![]莫名其妙地返回1,因为"false"[1]等于"a"

现在,让我们看看如何+!![]等于1

[]是一个空数组,你能想到的作为0这将是true在JavaScript(因为“在JavaScript什么‘真正的’是true) ,所以![]是false!![]true

现在我们剩下的+true这只是将true转换为1的数字。现在您可以看到+!![]的评估结果为1,并且您了解(希望)该混淆代码的工作原理!

3

理解这一点的关键是知道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 conversionsoperator precedence的更多信息。

隐式类型转换是经验丰富的JavaScript程序员在比较值时更喜欢使用===而不是==的原因。

2

下面是详细的一步发生了什么步骤:对数组文本操作

(!! +[] + "") [ +!![] ] 
// ^^^ 

+[]元加号,这相当于Number([])导致0See 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先生

Type Coercion

相关问题