Jouons un peu plus!
Commençons par nous amuser!:
//----------#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, essayons de comprendre ces comportements fous, un par un:
1) Ici, le {}est analysé comme un bloc de code vide. Sans attribution, négation, regroupement (avec parenthèses) ou toute syntaxe indiquant à l'analyseur qu'il {}s'agit d'un objet littéral, l'hypothèse par défaut est de penser qu'il s'agit simplement d'un bloc vide inutile.
Ceci est une preuve de ce comportement:
{ alert(123) }[true]
Le code ci-dessus affichera l'alerte normalement et sera évalué comme [true], de la même manière {}[true].
Bloquer les instructions sans point-virgule
Une instruction de type bloc n'a pas besoin d'un point-virgule après.
Par exemple:
for(var i=0; i < 1; i++){}function a(){};alert("Passed here!");if(true){}alert("Passed here too!")
Les deux alertes sont affichées.
Ainsi, nous pouvons voir qu'une instruction de bloc vide, sans point-virgule, est valide et ne fait simplement rien. De cette façon, lorsque vous entrez {}[true]dans la console Developer Tools (ou Firebug), la valeur évaluée sera la valeur de la dernière instruction d'expression . Dans ce cas, la dernière instruction d'expression est[true] .
2) Dans un contexte d'affectation, l'analyseur s'assurera qu'il {}s'agit d'un objet littéral. Lorsque vous faites var a = {}[true], vous supprimez toute ambiguïté et inclinez l'analyseur qui {}n'est pas une instruction de bloc.
Donc, ici, vous essayez d'obtenir une valeur avec une clé à "true"partir d'un objet vide. De toute évidence, il n'y a pas de paire clé-valeur avec ce nom de clé. De cette façon, la variable a n'est pas définie.
Mots réservés comme clés d'objet
ECMAScript 5 permet aux clés d'objet d'être des mots réservés. Ainsi, les clés suivantes sont légales:
var obj = {if: 111, for: 222, switch: 333, function: 444, true: 555}
3) La même explication de l'exemple 1 . Mais ... Si la { b: 12345 }partie est traitée comme une instruction de bloc, quel est le type de l' b: 12345instruction ??
... (?????)
C'est une déclaration d'étiquette , vous l'avez déjà vu auparavant ... Il est utilisé dans les boucles et dans switch. Voici quelques liens intéressants sur les instructions d'étiquette: 1 , (2) [Le meilleur moyen de rompre avec les boucles imbriquées en Javascript? , (3) [ Comment casser les boucles imbriquées en javascript? .
REMARQUE: essayez simplement d'évaluer ceci:
{a: 1, b: 2} //=>>>SyntaxError: Unexpected token :
Les instructions d'étiquette ne peuvent pas être séparées par l' opérateur virgule , vous devrez les séparer par un point-virgule. Donc ceci est valable:{a: 1; b: 2}
4) Voir les explications des exemples 1 et 3 ...
5) Une fois de plus, nous avons un { b: 12345 }être traité comme un bloc de code, et vous essayez d'accéder à une propriété d'un bloc de code en utilisant la notation par points , et évidemment, ce n'est pas autorisé, et l'analyseur lève une "Unexpected token :"exception.
6) Le code est presque identique à l'exemple ci-dessus, mais en entourant l' { b: 12345 }instruction avec l' opérateur de regroupement d'expression , l'analyseur saura qu'il s'agit d'un objet. De cette façon, vous pourrez accéder à la "b"propriété normalement.
7) Rappelez-vous l'exemple 2 , nous avons une affectation ici, l'analyseur sait que { b: 12345 }c'est un objet.
8) Identique à l'exemple ci-dessus, mais au lieu de la notation par points, nous utilisons ici la notation entre crochets .
9) J'ai déjà dit que cette "identifier: value"syntaxe à l'intérieur d'une instruction de bloc est une étiquette. Mais, vous devez également savoir qu'un nom d'étiquette ne peut pas être un mot-clé réservé (le contraire des noms de propriété d'objet). Lorsque nous avons essayé de définir une étiquette appelée "true", nous avons obtenu un SyntaxError.
10) Encore une fois, nous avons affaire à un objet. Aucun problème avec les mots réservés ici. =)
11) Enfin, nous avons ceci:!{}[true]
Séparons les choses ici:
a) En faisant une négation, nous informons l'analyseur que le {}est un objet .
b) Comme indiqué dans l'exemple 2 , un {}objet n'a pas de propriété appelée true, donc cette expression sera évaluée undefined.
c) Le résultat final est la négation de undefined valeur. Javascript effectue une conversion de type d'implicité et la undefinedvaleur est fausse .
d) Donc, la négation de falseest ...true !
var o = {}; o[true] === undefined.