Domanda

Oggi ho avuto una discussione con un collega sulle funzioni nidificate in Javascript:

function a() {
   function b() {
      alert('boo')
   }
   var c = 'Bound to local call object.'
   d = 'Bound to global object.'
}

In questo esempio, le prove indicano che b non è raggiungibile al di fuori del corpo di a, proprio come c è. Tuttavia, d è - dopo aver eseguito a (). Cercando la definizione esatta di questo comportamento nel ECMAScript v. 3 standard , non ho trovato la frase esatta che stavo cercando; ciò che Sec.13 p.71 non dice, è a quale oggetto deve essere associato l'oggetto funzione creato dall'istruzione dichiarazione di funzione. Mi sto perdendo qualcosa?

È stato utile?

Soluzione

Questo è scoping statico. Le istruzioni all'interno di una funzione sono nell'ambito di quella funzione.

Javascript ha un comportamento bizzarro, tuttavia è che senza la parola chiave var hai implicato una variabile globale . Questo è ciò che stai vedendo nel tuo test. Il tuo " d " La variabile è disponibile perché è un implicito globale, nonostante sia scritto nel corpo di una funzione.

Inoltre, per rispondere alla seconda parte della tua domanda: esiste una funzione in qualunque ambito sia dichiarata, proprio come una variabile.

Nota a margine: Probabilmente non vuoi variabili globali, specialmente non implicite. Si consiglia di utilizzare sempre la parola chiave var, per evitare confusione e mantenere tutto pulito.

Nota a margine: Lo standard ECMA non è probabilmente il posto più utile per trovare risposte su Javascript, sebbene non sia certamente una cattiva risorsa. Ricorda che javascript nel tuo browser è solo un'implementazione di quello standard, quindi il documento sugli standard ti fornirà le regole che sono state (per lo più) seguite dagli implementatori durante la costruzione del motore javascript. Non può offrire informazioni specifiche sulle implementazioni che ti interessano, in particolare i principali browser. Ci sono un paio di libri in particolare che ti daranno informazioni molto dirette su come si comportano le implementazioni javascript nei principali browser. Per illustrare la differenza, includerò di seguito alcuni estratti delle specifiche ECMAScript e un libro su Javascript. Penso che accetti che il libro dia una risposta più diretta.

Ecco dalle Specifiche della lingua ECMAScript :

  

10.2 Immettere un contesto di esecuzione

     

Ogni chiamata di funzione e costruttore   entra in un nuovo contesto di esecuzione, anche   se una funzione si sta chiamando da sola   in modo ricorsivo. Ogni ritorno esce un   contesto di esecuzione. Un'eccezione generata,   se non catturato, può anche uscire da uno o   più contesti di esecuzione.

     

Quando controllo   entra in un contesto di esecuzione, l'ambito   la catena viene creata e inizializzata,   viene eseguita l'istanza variabile,   e viene determinato questo valore.

     

Il   inizializzazione della catena di portata,   istanza variabile e il   la determinazione di questo valore dipende   sul tipo di codice inserito.

Ecco da O'Reilly's Javascript: The Definitive Guide (5th Edition) :

  

8.8.1 Scoping lessico

     

Le funzioni in JavaScript sono lessicali   piuttosto che con ambito dinamico. Questo   significa che funzionano nell'ambito   che sono definiti, non l'ambito   da cui vengono giustiziati. Quando un   la funzione è definita, l'ambito corrente   la catena viene salvata e diventa parte di   lo stato interno della funzione.   ...

Altamente raccomandato per coprire questo tipo di domande è il libro di Douglas Crockford:

JavaScript, The Good Parts http://oreilly.com/catalog/covers/9780596517748_cat.gif

Javascript, le parti buone , anche da O 'Reilly.

Altri suggerimenti

A quanto ho capito, sono equivalenti per quanto riguarda l'ambito:

function a() { ... }

e

var a = function() { ... }

Sembra importante notare che mentre d viene creato come "globale", in realtà viene creato come proprietà dell'oggetto finestra. Ciò significa che potresti inavvertitamente sovrascrivere qualcosa che esiste già sull'oggetto window o la tua variabile potrebbe non riuscire a essere creata. Quindi:

function a() {
    d = 'Hello World';
}
alert(window.d); // shows 'Hello World'

Ma non puoi farlo:

function a() {
    document = 'something';
}

perché non è possibile sovrascrivere l'oggetto window.document.

Per tutti gli scopi pratici puoi immaginare che tutto il tuo codice sia in esecuzione in un gigantesco con blocco (finestra) .

Javascript ha due ambiti. Globale e funzionale. Se dichiari una variabile all'interno di una funzione usando " var " parola chiave, sarà locale per quella funzione e tutte le funzioni interne. Se dichiari una variabile al di fuori di una funzione, ha portata globale.

Infine, se ometti la parola chiave var durante la prima dichiarazione di una variabile, javascript presume che tu volessi una variabile globale, indipendentemente da dove la dichiari .

Quindi, stai chiamando la funzione a e la funzione a sta dichiarando una variabile globale d.

...

function a() {
   function b() {
      alert('boo')
   }
   var c = 'Bound to local call object.'
   d = 'Bound to global object.'
}

senza essere preceduto da var , d è globale. Fallo per renderlo privato:

function a() {
   function b() {
      alert('boo')
   }
   var c = 'Bound to local call object.'
   var d = 'Bound to local object.'
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top