2010-01-15 16 views
11

Sono nuovo di Javascript e mi sono confuso dal funzionamento della dichiarazione di funzione. Ho fatto un po 'di test su questo e ottenuto alcuni risultati interessanti:Dichiarazione di funzione ambigua in Javascript

say(); 

function say() 
{ 
    alert("say"); 
} 

L'attaccante dichiarazione lavorato e pop-up "dire"

Al contrario

say(); 

say = function() 
{ 
    alert("say"); 
} 

non ha funzionato, anche se anche dichiarato oggetto funzione

Se dichiariamo la funzione e la dichiariamo in seguito:

Ho ottenuto "dire" invece di "parlare". È una sorpresa!

OK. Sembra che funzioni solo la dichiarazione delle funzioni più recente. Poi lascia dichiarare oggetto funzione prima e poi una funzione di "regolare":

say = function() 
{ 
    alert("speak"); 
} 

say(); 

function say() 
{ 
    alert("say"); 
} 

say(); 

Un'altra sorpresa, è stato "parlare" seguito da "parlare". La dichiarazione di funzione "regolare" non ha funzionato affatto!

C'è una spiegazione di tutti loro? E se la dichiarazione di funzione "regolare" è davvero così "fragile" e può essere facilmente sostituita dall'oggetto funzione con lo stesso nome, dovrei stare lontano da quello?

Un'altra domanda è: con solo il formato oggetto funzione, la dichiarazione anticipata diventa impossibile? C'è un modo per "simulare" quello in Javascript?

risposta

0

È possibile che le definizioni delle funzioni vengano applicate in ordine. Quindi tutte le righe di codice non di metodo verranno eseguite nell'ordine, compreso l'assegnazione di oggetti funzione. Questo spiega ognuno dei tuoi esempi. È comunque un problema interessante. Non è davvero possibile assegnare un oggetto funzione dopo il nel tentativo di chiamarlo e aspettarsi che funzioni. Tuttavia, una definizione di funzione che segue il codice eseguibile verrà effettivamente applicata per prima.

3

Javascript funziona così:

Il documento viene analizzato, e le function dichiarazioni sono tutte prese presi in considerazione subito, prima dell'esecuzione del bilancio effettivo verificarsi. Questo spiega il tuo primo esempio.

Se si assegna una funzione a una variabile locale, ciò avviene durante l'esecuzione, quindi non è possibile utilizzare il metodo nel secondo esempio.

Quello che si sperimenta è che se si dichiara una funzione due volte, l'ultima verrà utilizzata dall'intera applicazione. Questo è il tuo terzo esempio.

Queste funzioni sono rese membri dell'oggetto window, sono in effetti dichiarate globalmente. Se assegni una variabile locale a un valore di una funzione, allora quella variabile locale ha la precedenza sui membri nell'oggetto window. Se javascript non riesce a trovare una variabile locale, cerca all'interno di esso per trovarlo, l'oggetto window è l'ultima risorsa. Questo è quello che è successo nel tuo ultimo esempio, ha una variabile say che si trova in un ambito più specifico della funzione globale say.

Se ridichiarare say in fase di esecuzione, cioè scambiare l'ordine delle dichiarazioni nel tuo ultimo esempio, allora si dovrebbe vedere i due diversi avvisi che ci si aspetta:

say(); //speak, the global function 

function say() { 
    alert('speak'); 
} 

var say = function() { 
    alert('say'); 
} 

say(); //say, the declared local variable 
+0

Vedo i tuoi punti. Ma qual è lo scopo se definisco oggetti funzione locali? Ho provato a chiamare window.say() e il risultato non è ancora quello che mi aspettavo: function say() { alert("say"); } window.say(); popup "dire" e var say = function() { alert("speak"); } window.say(); function say() { alert("say"); } window.say(); popup "parlare" due volte. Significa che sia la funzione "globale" che l'oggetto "locale" sono membri dell'oggetto finestra? –

+0

scusa non so come formattare il commento ... :( –

+0

@Xiang: Il motivo per cui ottieni "speak" due volte è che l'interprete JavaScript fa due passaggi: nel primo, crea le proprietà dell'oggetto Variabile (che è usato per cercare variabili nell'attuale scope ed è l'oggetto globale nel codice globale) per le dichiarazioni 'var' e le dichiarazioni di funzione, e nel secondo passaggio esegue le istruzioni nell'ordine.Il punto cruciale è che' var' le affermazioni sono effettivamente suddivise in due: nel primo passaggio, una proprietà con valore 'indefinito' viene aggiunta all'oggetto Variable se non contiene già una proprietà con quel nome (continua ...) –

1
say(); 

function say() 
{ 
    alert("say"); 
} 

Qui le recupera interprete la definizione di say() quando viene chiamata e la esegue.

say(); 

say = function() 
{ 
    alert("say"); 
} 

Qui non esiste una definizione di say() per andare a prendere - invece si sta assegnando una funzione anonima a una variabile. L'interprete non può "trovare" questo come può trovare dichiarazioni in avanti.

function say() 
{ 
    alert("speak"); 
} 

say(); 

function say() 
{ 
    alert("say"); 
} 

Qui say è definito e quindi ridefinito - l'ultima definizione vince.

say = function() 
{ 
    alert("speak"); 
} 

say(); 

function say() 
{ 
    alert("say"); 
} 

say(); 

Qui say è una variabile che punta a una funzione anonima (dopo la prima istruzione viene interpretata). Questo ha la precedenza su qualsiasi definizione di funzione, come se avessi inserito la definizione della funzione prima dell'assegnazione.

Ma se si dovesse

say(); 

say = function() 
{ 
    alert("speak"); 
} 

say(); 

function say() 
{ 
    alert("say"); 
} 

Poi si otterrebbe "dire" seguito da "parlare".

0

È sempre una buona idea chiamare la funzione in seguito, anche se javascript funziona così.

La maggior parte delle lingue non funzionerà in questo modo, invece di farlo.

function say(){ 
    alert("say"); 
} 

say(); 

o

say = function(){ 
    alert("say"); 
} 

say(); 

o

(function(){ 
    alert("say"); 
})(); 
Problemi correlati