2009-11-30 18 views
20

In den Antworten auf this question lesen wir, dass function f() {} den Namen lokal definiert, während [var] f = function() {} es global definiert. Das macht Sinn für mich, aber es gibt ein merkwürdiges Verhalten, das sich zwischen den beiden Erklärungen unterscheidet.JavaScript: Wie unterscheidet sich "function onload() {}" von "onload = function() {}"?

ich eine HTML-Seite mit dem Skript gemacht

onload = function() { 
    alert("hello"); 
} 

und es funktionierte wie erwartet. Als ich es zu

function onload() { 
    alert("hello"); 
} 

änderte, passierte nichts. (Firefox hat immer noch das Ereignis ausgelöst, aber WebKit, Opera und Internet Explorer nicht, obwohl ich ehrlich gesagt keine Ahnung habe, welche korrekt ist.)

In beiden Fällen (in allen Browsern) konnte ich überprüfen, dass beide window.onload und onload wurden auf die Funktion eingestellt. In beiden Fällen wird das globale Objekt this auf das Fenster festgelegt, und egal wie ich die Deklaration schreibe, empfängt das window Objekt die Eigenschaft einwandfrei.

Was geht hier vor? Warum funktioniert eine Erklärung anders als die andere? Ist das eine Eigenart der JavaScript-Sprache, des DOM oder der Interaktion zwischen den beiden?

+1

Ich fange an zu vermuten, dass dies ein Fehler in Webkit/Opera ist und dass Firefox das richtige Verhalten hat. – Wogan

+0

Weder ist an sich korrekt. Das globale Objekt (auf das sich 'window' bezieht) kann Host-definierte Eigenschaften haben (wie 'onload') und eine ECMAScript3-Implementierung ist frei, das Verhalten einer solchen Eigenschaft zu implementieren, einschließlich der internen' [[Put ]] 'Methode, die aufgerufen wird, wenn der Wert der Eigenschaft zugewiesen wird. –

+0

In Firefox 3.5.5 sehe ich die Warnung, wenn ich 'onload = function() {...};' aber nicht mit 'var onload = function() {...};' –

Antwort

4

Diese beiden Snippets deklarieren eine Funktion im aktuellen Bereich namens "onload". Es wird keine Bindung vorgenommen.

function onload() { ... } 

.

var onload = function() { ... } 

Dieser Ausschnitt weist eine Funktion auf eine Eigenschaft/Variable/Feld mit dem Namen „onload“ auf dem aktuellen Bereich:

onload = function() { ... } 

Der Grund, warum Firefox im 1. die Bindung und hob das Onload-Ereignis ausgeführt Snippet und die anderen konnten nicht sein, weil Firefox Chrome (seine Benutzeroberfläche) selbst geschrieben und mit JavaScript automatisiert wurde - deshalb ist es so flexibel und einfach, Erweiterungen darauf zu schreiben. Irgendwie, wenn Sie die lokal-Bereich onload Funktion auf diese Weise erklärt, Firefox "ersetzt" window 's (wahrscheinlich der lokale Kontext zu der Zeit) Umsetzung von onload (zu dieser Zeit eine leere Funktion oder undefiniert), wenn die andere Browser "sandboxed" die Deklaration in einen anderen Bereich (zB global oder so).

+0

Gute Beobachtung, dass Firefox * in * JavaScript geschrieben wird. –

+1

Nun, nicht vollständig, aber die meisten seiner Chrom (Benutzeroberfläche) ist. –

0
var onload = function() { 
    alert("hello"); 
} 

Wird auch lokal deklariert.

Ich schlage vor, Sie diese sehr hilfreich Artikel zu lesen: http://kangax.github.io/nfe/

+2

Das ist ein großartiger Artikel, aber er beantwortet die Frage nicht. –

4

Viele Menschen sind unter Hinweis darauf, korrekt die globale/lokale Differenz zwischen (UPDATE: Diese Antworten wurden vor allem von ihren Autoren jetzt entfernt)

var x = function() { 

und

function x() { 

Aber das ist nicht wirklich die Antwort auf Ihre spezifische Frage, da Sie nicht die erste von diesen tun.

Der Unterschied zwischen den beiden in Ihrem Beispiel ist:

// Adds a function to the onload event 
onload = function() { 
    alert("hello"); 
} 

Während

// Declares a new function called "onload" 
function onload() { 
    alert("hello"); 
} 
+0

Vielleicht liegt es daran, dass letzterer zur Analyse ausgewertet wird, also ist das 'window' Objekt noch nicht bereit Ereignisse zu akzeptieren? –

+0

Das Deklarieren einer Funktion namens "onload" bindet sie nicht explizit an das onload-Ereignis - also müssten Sie den Browsern trotzdem mitteilen, dass sie die Funktion "onload" aufrufen sollen, wenn das Ereignis "onload" ausgelöst wird (obwohl einige davon ausgehen) . – Fenton

+0

Wirklich? Die Zuweisung einer Funktion zu "window.onload" funktioniert nach meiner Erfahrung gut. –

1

Hier ist, was ich denke, ist los, basierend auf Tim Down hilfreiche Kommentare und einer kurzen Diskussion mit Jonathan Penn :

Wenn der JavaScript-Interpreter der Eigenschaft window.onload zuweist, spricht er mit einem Objekt, das der Browser angegeben hat. Der Setter, den es aufruft, bemerkt, dass die Eigenschaft onload heißt, und geht so zum Rest des Browsers und verdrahtet das entsprechende Ereignis. All dies liegt außerhalb des Bereichs von JavaScript - das Skript sieht nur, dass die Eigenschaft festgelegt wurde.

Wenn Sie eine Erklärung function onload() {}, wird der Setter nicht in genau der gleichen Weise schreiben aufgerufen.Da die Deklaration eine Zuweisung bei parse Zeit, nicht Evaluierungszeit verursacht, geht der Skript-Interpreter weiter und erstellt die Variable, ohne den Browser zu informieren; oder das Fensterobjekt ist nicht bereit, Ereignisse zu empfangen. Was auch immer es ist, der Browser bekommt keine Chance, die Zuweisung zu sehen, wie wenn Sie onload = function() {} schreiben, was die normale Setter-Routine durchläuft.

-1

Dies erzeugt einen Fehler:

foo(); 
var foo = function(){}; 

Dies gilt nicht:

foo(); 
function foo(){} 

Die zweite Syntax ist daher schöner, wenn Sie Funktionen verwenden Sie den Code modularisieren und zu organisieren, während den ersten Syntax ist für das Funktionen-als-Daten-Paradigma schöner.

+0

Dies ist eine Antwort auf [var Funktionsname = Funktion() {} vs Funktion Funktionsname() {}] (http://stackoverflow.com/questions/336859/var-functionname-function-vs-function-functionname); Es beantwortet diese * Frage nicht, die Ereignisbindungen auf "Fenster" betrifft. – apsillers

0

Die einfachste Erklärung:

function aaaaaaa(){ 

Kann verwendet werden, bevor es declarated ist:

aaaaaaa(); 
function aaaaaaa(){ 

} 

Aber das funktioniert nicht:

aaaaaaa(); 
aaaaaaa=function(){ 

} 

das, weil im dritten Code ist , Sie ordnen aaaaaaa einer anonymen Funktion zu und deklarieren sie nicht als Funktion.