2009-11-30 2 views
20

В ответах на this question мы читаем, что function f() {} определяет имя локально, а [var] f = function() {} определяет его по всему миру. Это имеет для меня прекрасный смысл, но между этими двумя объявлениями существует какое-то странное поведение.JavaScript: Как работает функция onload() {} "отличается от" onload = function() {} "?

Я сделал страницу HTML со сценарием

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

, и она работала, как ожидалось. Когда я сменил его на

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

ничего не произошло. (Firefox все еще запускал событие, но WebKit, Opera и Internet Explorer этого не делал, хотя, честно говоря, я не знаю, что правильно.)

В обоих случаях (во всех браузерах) я мог убедиться, что оба window.onload и onload. В обоих случаях глобальный объект this установлен в окно, и я независимо от того, как я пишу объявление, объект window получает свойство просто отлично.

Что здесь происходит? Почему одно заявление работает иначе, чем другое? Является ли это причудой языка JavaScript, DOM или взаимодействия между ними?

+1

Я начинаю подозревать, что это ошибка в Webkit/Opera и что у Firefox есть правильное поведение. – Wogan

+0

Ни один из них не является правильным. Глобальный объект (к которому относится «окно») может иметь определенные в узле свойства (такие как 'onload'), и реализация ECMAScript 3 может реализовать поведение такого свойства, которое оно считает нужным, включая внутренний' [[Put ]] ', который вызывается при назначении значения свойства. –

+0

В Firefox 3.5.5 я вижу предупреждение, если я использую 'onload = function() {...};', но не с 'var onload = function() {...};' –

ответ

4

Этот два фрагмента объявляет функцию в текущей области действия под названием «onload». Никакой привязки не делается.

function onload() { ... } 

.

var onload = function() { ... } 

Этот фрагмент кода присваивает функцию в свойство/переменной/поле с именем «OnLoad» на текущей области:

onload = function() { ... } 

Причина, почему Firefox выполняется связывание и вызвавший событие OnLoad на 1 фрагмент и другие, возможно, не потому, что Firefox Chrome (его пользовательский интерфейс) сам написан и автоматизирован с использованием JavaScript - вот почему он настолько гибкий и простой в написании расширений на нем. Так или иначе, когда вы объявили локально локализованную функцию onload таким образом, Firefox «заменил» реализацию window (скорее всего, локальный контекст в то время) onload (в то время пустую функцию или неопределенный), когда другой браузеры правильно «изолировали» декларацию в другую область (скажем, global или что-то).

+0

Хорошее наблюдение, что Firefox написан * в * JavaScript. –

+1

Ну, не совсем, но большая часть его хром (пользовательский интерфейс). –

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

Будет объявлено также локально.

Я предлагаю вам прочитать эту очень полезную статью: http://kangax.github.io/nfe/

+2

Это отличная статья, но она не отвечает на вопрос. –

4

Многих люди правильно указывая на глобальную/локальную разницу между (UPDATE: Эти ответы были в основном удалены их авторами в настоящее время)

var x = function() { 

и

function x() { 

Но что на самом деле не ответить на ваши конкретный вопрос, поскольку вы на самом деле не делаете первый из них.

Разница между ними в вашем примере:

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

В то время как

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

Возможно, это потому, что последний получает оценку во время разбора, поэтому объект 'window' еще не готов принять события? –

+0

Объявление функции, называемой «onload», явно не привязывает ее к событию onload, поэтому вам все равно нужно будет сказать браузеру, чтобы вызвать функцию «onload» при срабатывании события «onload» (хотя некоторые могут предположить, что это так) , – Fenton

+0

Действительно? Назначение функции 'window.onload' хорошо работает в моем опыте. –

1

Вот что я думаю, что это происходит, основываясь на полезные комментарии Тима Дауна и краткое обсуждение с Джонатаном Пенна :

Когда интерпретатор JavaScript присваивает свойству window.onload, он разговаривает с объектом, который предоставил браузер. Установитель, который вызывает уведомления о том, что свойство называется onload, и поэтому переходит к остальной части браузера и подключает соответствующее событие. Все это выходит за рамки JavaScript - скрипт просто видит, что свойство было установлено.

Когда вы пишете объявление function onload() {}, сеттер не вызывается аналогичным образом.Поскольку объявление вызывает назначение при parse время, а не время оценки, интерпретатор сценариев идет вперед и создает переменную без указания браузера; либо оконный объект не готов принимать события. Независимо от того, что это такое, браузер не получает возможность видеть назначение, как это происходит, когда вы пишете onload = function() {}, который проходит обычную процедуру настройки.

-1

Это приводит к ошибке:

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

Это не:

foo(); 
function foo(){} 

Второй синтаксис, поэтому лучше, когда вы используете функцию модуляризировать и организовать свой код, в то время как первый синтаксис лучше для парадигмы функций как данных.

+0

Это ответ на [var functionName = function() {} vs function functionName() {}] (http://stackoverflow.com/questions/336859/var-functionname-function-vs-function-functionname); он не отвечает на этот * вопрос, связанный с привязкой событий к 'window'. – apsillers

0

Самое простое объяснение:

function aaaaaaa(){ 

Может использоваться, прежде чем он declarated:

aaaaaaa(); 
function aaaaaaa(){ 

} 

Но это не работает:

aaaaaaa(); 
aaaaaaa=function(){ 

} 

Это потому, что в третьем коде , вы назначаете aaaaaaa анонимной функции, а не объявляете ее как функцию.

Смежные вопросы