Lass uns ein bisschen mehr spielen!
Lass uns zuerst ein bisschen Spaß haben!:
//----------#01#-----------
{}[true]; //[true]
//----------#02#-----------
var a = {}[true];
console.log(a); //undefined
//----------#03#-----------
{ b: 12345 }[true]; //[true]
//----------#04#-----------
{ b: 12345 }["b"]; //evaluates to ["b"] ?!?
//----------#05#-----------
{ b: 12345 }.b; // "Unexpected token ."
//----------#06#-----------
({ b: 12345 }).b; //12345
//----------#07#-----------
var c = { b: 12345 }.b;
console.log(c); //12345
//----------#08#-----------
var c = { b: 12345 }["b"];
console.log(c); //12345
//----------#09#-----------
{ true: 54321 }[true]; // "SyntaxError: Unexpected token : "
//----------#10#-----------
var d = { true: 54321 }[true]; //No error here ¬¬
console.log(d); //54321
//----------#11#-----------
!{}[true]; // true
Ok, lass uns versuchen, diese verrückten Verhaltensweisen einzeln zu verstehen:
1) Hier wird das {}als leerer Codeblock analysiert. Ohne Zuweisung, Negation, Gruppierung (mit Klammern) oder einer Syntax, die dem Parser anzeigt, dass dies {}ein Objektliteral ist, wird standardmäßig angenommen, dass es sich einfach um einen nutzlosen leeren Block handelt.
Dies ist ein Beweis für dieses Verhalten:
{ alert(123) }[true]
Der obige Code zeigt die Warnung normalerweise, und wie bewertet wird [true], in der gleichen Art und Weise {}[true]ist.
Blockanweisungen ohne Semikolons
Eine blockartige Anweisung benötigt danach kein Semikolon.
Zum Beispiel:
for(var i=0; i < 1; i++){}function a(){};alert("Passed here!");if(true){}alert("Passed here too!")
Beide Warnungen werden angezeigt.
Wir können also sehen, dass eine leere Blockanweisung ohne Semikolon gültig ist und einfach nichts bewirkt. Auf diese Weise ist {}[true]der ausgewertete Wert beim Aufrufen der Developer Tools (oder Firebug) -Konsole der Wert der letzten Ausdrucksanweisung . In diesem Fall lautet die letzte Ausdrucksanweisung[true] .
2) In einem Zuweisungskontext stellt der Parser sicher, dass {}es sich um ein Objektliteral handelt. Wenn Sie var a = {}[true]ausführen, entfernen Sie alle Mehrdeutigkeiten und geben dem Parser {}einen Hinweis , der keine Blockanweisung ist.
Hier versuchen Sie also, mit einem Schlüssel einen Wert zu erhalten"true" von einem leeren Objekt abzurufen. Offensichtlich gibt es kein Schlüssel-Wert-Paar mit diesem Schlüsselnamen. Auf diese Weise ist die Variable a undefiniert.
Reservierte Wörter als Objektschlüssel
Mit ECMAScript 5 können Objektschlüssel reservierte Wörter sein. Die folgenden Schlüssel sind also legal:
var obj = {if: 111, for: 222, switch: 333, function: 444, true: 555}
3) Die gleiche Erklärung von Beispiel 1 . Aber ... Wenn das { b: 12345 }Teil als Blockanweisung behandelt wird, wie lautet die Art der b: 12345Anweisung?
... (?????)
Es ist eine Label-Anweisung , die Sie bereits gesehen haben ... Sie wird in Loops und in verwendet switch. Hier sind einige interessante Links zu Label-Anweisungen: 1 , (2) [Der beste Weg, um aus verschachtelten Schleifen in Javascript auszubrechen? , (3) [ Wie werden verschachtelte Schleifen in Javascript unterbrochen? .
HINWEIS: Versuchen Sie einfach, dies zu bewerten:
{a: 1, b: 2} //=>>>SyntaxError: Unexpected token :
Label-Anweisungen können vom Komma- Operator nicht getrennt werden. Sie müssen sie mit einem Semikolon trennen. Das ist also gültig:{a: 1; b: 2}
4) Siehe die Erläuterungen zu den Beispielen 1 und 3 ...
5) Noch einmal, wir werden { b: 12345 }als Codeblock behandelt, und Sie versuchen, mithilfe der Punktnotation auf eine Eigenschaft eines Codeblocks zuzugreifen. Dies ist natürlich nicht zulässig, und der Parser löst eine "Unexpected token :"Ausnahme aus.
6) Der Code ist fast identisch mit dem obigen Beispiel, aber durch Umgeben der { b: 12345 }Anweisung mit dem Ausdrucksgruppierungsoperator weiß der Parser, dass es sich um ein Objekt handelt. Auf diese Weise können Sie "b"normal auf die Unterkunft zugreifen .
7) Denken Sie an Beispiel 2 , wir haben hier eine Zuordnung, der Parser weiß, dass { b: 12345 }es sich um ein Objekt handelt.
8) Identisch mit dem obigen Beispiel, aber anstelle der Punktnotation verwenden wir hier die Klammernotation .
9) Ich habe bereits gesagt, dass diese "identifier: value"Syntax in einer Blockanweisung eine Bezeichnung ist. Sie müssen jedoch auch wissen, dass ein Labelname kein reserviertes Schlüsselwort sein kann (das Gegenteil von Objekteigenschaftsnamen). Als wir versuchten, ein Label namens zu definieren "true", bekamen wir ein SyntaxError.
10) Wir haben es wieder mit einem Objekt zu tun. Keine Probleme mit reservierten Wörtern hier. =)
11) Schließlich haben wir Folgendes:!{}[true]
Lassen Sie uns die Dinge hier trennen:
a) Durch eine Negation informieren wir den Parser, dass {}es sich um ein Objekt handelt .
b) Wie in Beispiel 2 gezeigt , hat ein {}Objekt keine aufgerufene Eigenschaft true, daher wird dieser Ausdruck als ausgewertet undefined.
c) Das Endergebnis ist die Negation des undefinedWertes. Javascript führt eine Konvertierung des Implizitätstyps durch , und der undefinedWert ist falsch .
d) Die Negation von falseist also ... true!
var o = {}; o[true] === undefined.