2015-05-16 8 views
8
var namepace = (function() { 

    var loca = 5; 

    var getLocal = function() { 
     loca += 1; 
     return loca; 
    }; 

    return { 
     glob: getLocal, 
     blog: loca, 
     frog: function() { 
      return loca; 
     } 
    }; 
})(); 

alert(namepace.glob()); 
alert(namepace.blog); 
alert(namepace.frog()); 

mia domanda è perché fa il ritorno funzione di alert(namepace.blog);5 piuttosto che 6 come ci si aspetta?Javascript portata variabile e il valore

risposta

6

La cosa importante da capire qui è che tutti i nomi in JavaScript sono riferimenti ad altri oggetti.

Quando si crea un oggetto con letterale Oggetto, i nomi di sinistra vengono utilizzati per riferirsi agli oggetti già indicati dai nomi dei lati di destra.

In questo caso, quando si fa

blog: loca, 

stai dicendo blog per riferirsi al valore di cui da loca, che è 5. In seguito quando si incrementa loca, diventa 6, vuol dire che si riferisce a qualche altro valore, ma blog si riferisce ancora al valore 5.

Ecco perché ci si trova 5.

Ma quando lo fai

namepace.frog() 

si stanno ottenendo il valore corrente di cui da loca. Poiché viene assegnato 6 in getLocal, stai ricevendo 6.

Incremento crea nuovo oggetto numero

Per rendere ancora più chiaro, quando si fa

loca += 1; 

o

loca++; 

ciò che accade internamente a dire, qualcosa di simile

oldValue = loca 
newValue = oldValue + 1 
loca = newValue 

di riferimento da ECMAScript 5.1 Specifiche, per += e per ++

Dato che i numeri sono oggetti immutabili (si può cambiare il valore di 5? Non è possibile, è per questo che viene chiamato un oggetto immutabile), viene creato un nuovo oggetto numero con uno aggiunto e il nome loca viene creato per fare riferimento al nuovo oggetto.


oggetti mutabili

Se ci pensate oggetti mutabili,

var namepace = (function() { 

    var loca = []; 

    return { 
     glob: function() { 
      loca.push(1); 
      return loca; 
     }, 
     blog: loca, 
     frog: function() { 
      return loca; 
     } 
    }; 
})(); 

console.log(namepace.glob()); 
// [ 1 ] 
console.log(namepace.blog); 
// [ 1 ] 
console.log(namepace.frog()); 
// [ 1 ] 

Ora, sia blog e loca si riferiscono allo stesso oggetto array. Quello che succede in glob si chiama mutazione.Stai semplicemente aggiungendo un elemento all'array oggetto con due nomi blog e loca. Ecco perché namepace.blog stampa anche [ 1 ].

1

è un problema logico. quando la funzione richiede un po 'di tempo. in quel tempo variabile assegnata .. guarda sotto il codice. e provare questo

var namepace = (function() { 

    var loca = 5; 

    var getLocal = function() { 
     loca += 1; 
     return loca; 
    }; 
    console.log(loca); 

    return { 
     glob: getLocal, 
     blog: loca, 
     frog: function() { 
      return loca; 
     } 
    }; 
})(); 

alert(namepace.glob()); 
alert(namepace.blog); 
alert(namepace.frog()); 
0

Quando si assegnano a namespace.blog, si utilizza passaggio per valore per il setter. Ciò significa che non vi è alcun riferimento a loca.

Quando si accede al valore tramite namespace.frog, si utilizza la variabile originale, che utilizza l'ambito di chiusura di JavaScript per risolverlo su loca, la successiva definizione disponibile sulla catena di ambito locale.

Si può leggere su scoping qui: What is the scope of variables in JavaScript?

1

Aiuta a pensare al contesto di esecuzione quando un programma JavaScript viene eseguito. JavaScript valuta i riferimenti (non i valori direttamente).

Il contesto globale è costituito da variabili e oggetti globali. In questo caso è (al momento l'interprete JavaScript legge l'istruzione di namespace):

namespace = {f} // namespace references a function 

Ciò significa namespace fa riferimento una funzione. Al primo avviso viene creato il seguente contesto di esecuzione per lo spazio dei nomi:

loca = 5    // loca references the value 5 
getLocal = {f}   // getLocal references a function 
return {    // return object with glob, blog and frog as properties 
    glob = { getLocal() } // references the function getLocal() 
    blog = 5    // blog references same value as loca: 5 
    frog = {f}   // references anonymous function 
} 

Di conseguenza viene chiamato il glob di funzione. glob fa riferimento a una funzione chiamata getLocal. contesto di esecuzione di glob è la seguente:

loca = 6  // loca now references the value 6 
return loca // return value referenced by loca 

La chiamata successiva è blog e questo restituisce il valore 5. non fa riferimento loca. Si riferisce semplicemente al valore che loca aveva quando creava il contesto di esecuzione. Nel momento in cui il contesto di esecuzione è stato creato, il valore di riferimento è 5, quindi il blog fa riferimento al valore di 5. Non importa quanto spesso chiami glob, il blog continuerà a fare riferimento al valore di 5.

Nell'ultimo avviso la frase rana è invocata. rana fa riferimento a una funzione anonima che viene ora eseguita. contesto di esecuzione di rana è il seguente

return loca // Go and get the value that is referenced by loca 

Questo è fondamentalmente. Prova a pensare "riferimento a un valore" ogni volta che pensi valore. Questo può aiutare ad abituarsi ad esso. E prova a visualizzare i contesti di esecuzione quando viene eseguito un programma (come essere un debugger umano).