Подтвердить что ты не робот

JavaScript: Как "function onload() {}" отличается от "onload = function() {}"?

В ответах на этот вопрос мы читаем, что function f() {} определяет имя локально, а [var] f = function() {} определяет его глобально. Это имеет для меня смысл, но есть странное поведение, которое отличается между двумя объявлениями.

Я сделал HTML-страницу с script

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

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

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

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

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

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

4b9b3361

Ответ 1

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

function onload() { ... }

.

var onload = function() { ... }

Этот фрагмент присваивает функции свойству/переменной/поле с именем "onload" в текущей области:

onload = function() { ... }

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

Ответ 2

Многие люди правильно указывают на глобальную/локальную разницу между (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");
}

Ответ 3

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

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

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

Ответ 4

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

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

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

Ответ 5

Простейшее объяснение:

function aaaaaaa(){

Может использоваться до его объявления:

aaaaaaa();
function aaaaaaa(){

}

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

aaaaaaa();
aaaaaaa=function(){

}

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

Ответ 6

Это создает ошибку:

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

Это не означает:

foo();
function foo(){}

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