2017-05-28 4 views
6

Ich habe einen verschleierten JavaScript-Code gefunden. Ich versuchte es zu verstehen, und dabei tippte ich Teile davon in die Konsole. Ich kann nicht verstehen, warumWarum wird dieser Ausdruck in JavaScript zu "a" ausgewertet?

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

Warum ((!!+[]+"")[+!![]]) gleich "a" in JavaScript ist? Gibt es andere Code-Schnipsel, um andere Buchstaben zu erhalten?

Ich denke, es ist etwas mit dem automatischen Gießen zu tun.

+4

Das Ganze kann vereinfacht werden, um '("false"[1])'. Jetzt wissen Sie, warum das Ergebnis "a" ist. – abhishekkannojia

+0

a ist der zweite Buchstabe von false. Clever ^^ – WayToDoor

+2

[siehe hier] (https://github.com/aemkei/jsfuck/blob/master/jsfuck.js) –

Antwort

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

Gibt es einige andere Code-Schnipsel andere Briefe zu bekommen?

Sie mit dem gleichen Konzept spielen kann, alle Briefe bekommen von „true“, „false“, „unbestimmt“, „NaN“ ...

+1

Das ist die richtige Antwort. – SVSchmidt

+1

Warum ist '+ []' gleich 0? Vermute es konvertiert leere Array in Zahl, also, warum nicht 0 ... aber das verdient eine kleine Linie, denke ich ... und besser als ich denke, wenn möglich :) –

+0

@HuguesMoreau die unäre plus Operation '+' ist Parsing '[ ] 'zu einer Nummer – pomber

4

Sie auf Operator-Vorrang und Art Gussteilen arbeiten sollten in 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 

Und zumindest

"false"[1] // Is "a" 
+2

Haben Sie eine gute Referenz für Operatoren Vorrang in JavaScript? –

+0

mozilla Dokumentation ist gut genug, glaube ich. Ich beziehe mich immer dort. https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table – marmeladze

4

Lasst uns die Konsole verwenden, um unsere Antwort zu bekommen vorausgesetzt, wir wissen nicht, was das alles bedeutet, die Eingabe

[] + "" in den Konsolen-Ausgänge ""

gerade dabei (!!+[]) gibt den Boolean false. Wenn Sie den Booleschen Wert false an "" anhängen, erhalten Sie die Zeichenfolge false wegen der Typzwingung.

Wie erwartet, gibt (!!+[]+"") Ausgaben "false" an die Konsole.

In JavaScript können Sie sich Strings wie ein Array von Zeichen vorstellen und mit der Array-Notation auf ihr Zeichen zugreifen.

In ((!!+[]+"")[+!![]]) können Sie also die äußersten Klammern entfernen, um es einfacher zu machen. Jetzt haben wir (!!+[]+"")[+!![]] in dem der erste Teil in () die Zeichenfolge "false" zurückgibt, und der nächste Teil in [] greift auf ein Zeichen der Zeichenfolge "false". Sie können jetzt wetten, dass +!![] irgendwie 1 zurückgibt, da "false"[1] gleich "a" ist.

Nun lasst uns herausfinden, wie +!![] gleich 1:

[] ist ein leeres Array, das Sie als 0 denken können, welche true in JavaScript wäre (weil "in JavaScript nichts 'real' ist true") , so! [] ist false und !![] ist true.

Jetzt sind wir mit +true, die nur Kurzbezeichnung für true zu einer Zahl, die 1 sein würde.Jetzt können Sie sehen, wie +!![] zu 1 auswertet und Sie verstehen (hoffentlich), wie dieses verschleierte Stück Code funktioniert!

3

Der Schlüssel zum Verständnis besteht darin zu wissen, dass JavaScript implizite Typumwandlungen ausführt, um Ausdrücke auszuwerten, die es sieht. Mit anderen Worten: Während Sie vielleicht nicht wissen, was es bedeutet, einer Zeichenkette eine Zahl hinzuzufügen, führt JavaScript eine Vermutung durch, anstatt einen Fehler zu erzeugen. Es steht im Gegensatz zu dem, was Sie in C++ bekommen würden, was in diesem Fall einen expliziten Fehler ergibt.

Zum Beispiel wird +x immer zu einer Zahl ausgewertet, egal welcher Typ x tatsächlich ist. Dasselbe gilt für !x. Daher ist für Ihren Ausdruck:

// A: !!+[]+"" which is evaluated like !(!(+[]))+"" 
+[]  === 0 
!0  === true 
!true  === false 
false+'' === 'false' 

// B: +!![] which is evaluated like +(!(![])) 
![]  === false 
!false === true 
+true  === 1 

wir bekommen A[B] die einfach 'false'[1] === 'a' ist.

Sie können mehr über implicit type conversions und operator precedence bei MDN erfahren.

Implizite Typumwandlungen sind der Grund, warum erfahrene JavaScript-Programmierer beim Vergleichen von Werten lieber === als == verwenden.

2

Hier detaillierte Schritt für Schritt, was geschieht:

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

+[] Unäres Plus auf Arrayliteral arbeitet, die Number([]) entspricht, der in 0 führt. See this warum dies 0 auswertet.

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

!!0 ist !!Boolean(0)) äquivalent zu der seit false auswertet 0 falsy Wert.

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

false+"" ist einfach String-Verkettung wertet daher "false"

"false" [ +!![] ] 
//   ^^^^ 

!![] entspricht !!Boolean([]) und da Boolesche Umwandlung von Objekten zurückgibt immer wahr. Dies ergibt true.

"false" [ +true ] 
//  ^^^^^ 

+true ist Number(true) äquivalent, die an 1 auswertet.

"false" [ 1 ] 

die schließlich a ist.

Der Schlüsselpunkt hier ist Javascript implizit Typ Konvertierung oder Typ Koerzition während der Auswertung der Ausdrücke. Um mehr über Type Coercion zu erfahren, empfehle ich diese ausgezeichnete Ressource von Dr.Axel Rauschmayer

Type Coercion

Verwandte Themen