2009-11-10 14 views
14

Sto sperando che qualcuno può spiegarmi perché il sottostante JavaScript/HTML mostrerà "porta # 2" quando il codice HTML viene visualizzato in un browser:riferimento a un valore di JavaScript prima che venga dichiarata - qualcuno può spiegare questo

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
    <script type="text/javascript"> 
     function testprint() { 
      alert('door #1'); 
     }; 

     window.onload = testprint; 

     function testprint() { 
      alert('door #2'); 
     }; 

     testprint = function() { 
      alert('door #3'); 
     }; 
    </script> 
    <script type="text/javascript"> 
     function testprint() { 
      alert('door #4'); 
     }; 
    </script> 
</head> 
<body> 
</body> 
</html> 

Poiché solo la dichiarazione testprint si verifica prima window.onload è impostato su testprint, mi sarei aspettato window.onload causa 'porta # 1' di presentarsi. In realtà, l'onload causa la "porta n. 2". Si noti che lo farà se la prima dichiarazione di testprint è inclusa o meno.

La terza e quarta dichiarazione di testprint utilizzano diversi mezzi di assegnare la funzione, ho provato questo per vedere se si sovrapporrà window.onload s' comportamento nella stessa era il secondo dichiarazione di testprint fa. Io non l'ho fatto. Si noti che se si sposta la quarta dichiarazione di testprint alla fine del primo blocco di script, verrà chiamata da window.onload.

risposta

38

dichiarazioni di funzione sono oggetto di sollevamento, e vengono valutati in fase di analisi, dal sollevamento significa che sono disponibili per l'intero ambito in cui sono state dichiarate, ad esempio:

foo(); // alerts foo 
foo = function() { alert('bar')}; 
function foo() { alert('foo');} 
foo(); // alerts bar 

La prima chiamata a foo eseguirà la funzione dichiarazione, perché a fase di analisi è stato reso disponibile, la seconda chiamata di foo eseguirà la funzione espressione, dichiarati nella runtime.

Per una discussione più dettagliata sulle differenze tra le espressioni di funzione e le dichiarazioni di funzione, controllare this question e this article.

+0

C'è una sottigliezza per il funzionamento di sollevamento dove [i browser non sono d'accordo] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope#Conditionally_defining_a_function). _SpiderMonkey_ ** non ** elabora le funzioni dichiarate in un ambito condizionale mentre _V8_ (al momento della scrittura) lo fa. –

-1

testprint della funzione è globale alla pagina. testprint = function ... assegna una variabile, che non sono sicuro esattamente dell'intero ambito, ma ho l'impressione che non sia stata aggiunta al dizionario della tabella delle funzioni come la prima.

0

Il motivo # 3 non cambia window.onload è che le funzioni vengono chiamate per riferimento, non per nome. Quando si imposta window.onload = testprint, assegna il riferimento al valore corrente di testprint (porta n. 2, come spiegato da CMS) a window.onload. Il valore successivo di testprint non influisce sul valore di window.onload.

La porta n. 4 non sostituisce la porta n. 2 (a meno che, come hai detto, non la si sposti sul primo blocco di script) perché si trova in un blocco di script diverso, quindi viene analizzata dopo il completamento del primo blocco.

Problemi correlati