Giochiamo un po 'di più!
Per prima cosa, divertiamoci un po '!:
//----------#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, proviamo a capire questi comportamenti folli, uno per uno:
1) Qui, {}viene analizzato come un blocco di codice vuoto. Senza assegnazione, negazione, raggruppamento (con parentesi) o qualsiasi sintassi che indica al parser che si {}tratta di un oggetto letterale, il presupposto predefinito è di pensare che sia semplicemente un blocco vuoto inutile.
Questa è una prova di questo comportamento:
{ alert(123) }[true]
Il codice sopra mostrerà l'avviso normalmente e verrà valutato come [true], allo stesso modo{}[true] .
Dichiarazioni di blocco senza punto e virgola
Un'istruzione di tipo blocco non ha bisogno di un punto e virgola dopo di essa.
Per esempio:
for(var i=0; i < 1; i++){}function a(){};alert("Passed here!");if(true){}alert("Passed here too!")
Vengono visualizzati entrambi gli avvisi.
Quindi, possiamo vedere che un'istruzione di blocco vuota, senza punto e virgola, è valida e semplicemente non fa nulla. In questo modo, quando si accede {}[true]alla Console Strumenti di sviluppo (o Firebug), il valore valutato sarà il valore dell'ultima espressione espressione . In questo caso, l'ultima istruzione espressione è [true].
2) In un contesto di assegnazione, il parser si assicurerà che {}sia un oggetto letterale. Quando si var a = {}[true], si rimuove qualsiasi ambiguità e si annulla il parser che {}non è un'istruzione di blocco.
Quindi, qui, stai cercando di ottenere un valore con una chiave "true"da un oggetto vuoto. Ovviamente, non esiste una coppia chiave-valore con questo nome chiave. In questo modo, la variabile a non è definita.
Parole riservate come chiavi dell'oggetto
ECMAScript 5 consente alle chiavi dell'oggetto di essere parole riservate. Quindi, le seguenti chiavi sono legali:
var obj = {if: 111, for: 222, switch: 333, function: 444, true: 555}
3) La stessa spiegazione dell'esempio 1 . Ma ... Se la { b: 12345 }parte viene trattata come un'istruzione block, qual è il tipo di b: 12345istruzione ??
... (?????)
È una dichiarazione dell'etichetta , l'hai già vista prima ... È usata nei loop e dentro switch. Ecco alcuni link interessanti sulle dichiarazioni delle etichette: 1 , (2) [Il modo migliore per interrompere i loop nidificati in Javascript? , (3) [ Come interrompere i loop nidificati in JavaScript? .
NOTA: prova a valutare questo:
{a: 1, b: 2} //=>>>SyntaxError: Unexpected token :
Le istruzioni dell'etichetta non possono essere separate dall'operatore virgola , è necessario separarle con un punto e virgola. Quindi questo è valido:{a: 1; b: 2}
4) Vedi le spiegazioni per gli esempi 1 e 3 ...
5) Ancora una volta, ci { b: 12345 }viene trattato come un blocco di codice e si sta tentando di accedere a una proprietà di un blocco di codice utilizzando la notazione punto e, ovviamente, ciò non è consentito e il parser genera "Unexpected token :"un'eccezione.
6) Il codice è quasi identico all'esempio precedente, ma circondando l' { b: 12345 }istruzione con l' operatore di raggruppamento di espressioni , il parser saprà che è un oggetto. In questo modo, sarai in grado di accedere "b"normalmente alla proprietà.
7) Ricorda l'esempio 2 , qui abbiamo un compito, il parser sa che { b: 12345 }è un oggetto.
8) Identico all'esempio sopra, ma invece della notazione punto, qui stiamo usando la notazione parentesi .
9) Ho già detto che questa "identifier: value"sintassi all'interno di un'istruzione block è un'etichetta. Ma devi anche sapere che il nome di un'etichetta non può essere una parola chiave riservata (l'opposto dei nomi delle proprietà degli oggetti). Quando abbiamo provato a definire un'etichetta chiamata "true", abbiamo ottenuto un SyntaxError.
10) Ancora una volta, abbiamo a che fare con un oggetto. Nessun problema con le parole riservate qui. =)
11) Infine, abbiamo questo:!{}[true]
Separiamo le cose qui:
a) Facendo una negazione, stiamo informando il parser che {}è un oggetto .
b) Come mostrato nell'esempio 2 , un {}oggetto non ha una proprietà chiamata true, quindi questa espressione verrà valutata undefined.
c) Il risultato finale è la negazione del undefinedvalore. Javascript esegue la conversione del tipo di implicità e il undefinedvalore è errato .
d) Quindi, la negazione di falseè ... true!
var o = {}; o[true] === undefined.