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 или взаимодействия между двумя?

Ответ 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(){}

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