Ambito di equivoco in JavaScript?

5

Ho visto un pochi altro gli sviluppatori parlano di scope vincolanti in JavaScript, ma mi è sempre sembrato che questa frase sia imprecisa. Function.prototype.call e Function.prototype.apply non passano l'ambito tra due metodi; cambiano il chiamante della funzione - due cose molto diverse. Ad esempio:

function outer()
{
    var item = { foo: 'foo' };
    var bar = 'bar';
    inner.apply(item, null);
}

function inner()
{
    console.log(this.foo); //foo
    console.log(bar);      //ReferenceError: bar is not defined
}

Se l'ambito di outer è stato realmente passato a inner , mi aspetto che inner sia in grado di accedere a bar , ma non può. bar era nell'ambito in outer ed è fuori ambito in inner . Quindi, l'ambito non è stato superato. Anche i documenti Mozilla non menzionano nulla sul passaggio dell'ambito:

Calls a function with a given this value and arguments provided as an array.

Sto fraintendendo l'ambito o specificamente l'ambito in cui si applica a JavaScript? O sono questi altri sviluppatori che lo fraintendono?

    
posta Jeff 18.09.2012 - 19:07
fonte

3 risposte

3

Hai ragione. È meglio pensare in termini di contesto dell'oggetto rispetto allo scope con call e apply. Tuttavia, questo esempio seguente potrebbe essere visto come rendere un ambito accessibile a un altro contesto di oggetto:

function objFactory(){
    var someProperty = 'a property of some sort';
    this.getSomeProperty = function(){ return someProperty; };
}

var someObj = new objFactory(),
somePlainObj = {};

'a property of some sort' === someObj.getSomeProperty.apply(somePlainObj);//true

Potrei non avere i dettagli esatti, ma penso che gli oggetti JS costruiti dai costruttori di funzioni siano fondamentalmente solo funzioni che vengono copiate (insieme ai loro ambiti - gli ambiti js sono solo funzione), eseguiti, e quindi semplicemente mai garbage collector (così tutti i valori sono persistenti) e assegnati a uno spazio dei nomi è possibile accedere alle loro proprietà definite internamente modificando le regole "this" quando invocate con la parola chiave 'new'. Ma le vars interne non sono esattamente proprietà private (anche se tendiamo a pensarle in questo modo). Sono proprietà del costruttore di funzioni a cui si accede tramite i metodi tramite la chiusura.

Ma la prima parte del processo è ancora come una funzione che si attiva. Questo rende la var interna accessibile tramite closure che è come una copia dell'oscilloscopio nel momento in cui il costruttore ha terminato il passo di esecuzione della funzione.

    
risposta data 18.09.2012 - 19:36
fonte
3

Quando chiami inner.apply (elemento, null) chiami inner () come se fosse un metodo dell'elemento oggetto che ha foo definito su di esso. Questo imposta l'oggetto questo in inner () per essere elemento . Non stai davvero esponendo l'ambito della funzione outer () alla funzione inner () . Stai passando l'oggetto (e puoi quindi accedere ai suoi attributi). Non stai passando lo scope lessicale della funzione che ha definito quell'oggetto.

    
risposta data 18.09.2012 - 19:32
fonte
2

Guarda link , la serie di articoli "Learning JavaScript with Object Graphs". apply e call sono la cosa più magica in JS (probabilmente insieme all'oscuramento della chiusura), non puoi capirlo completamente a meno che tu non comprenda le basi.

    
risposta data 18.09.2012 - 19:39
fonte

Leggi altre domande sui tag