Ответ 1
Примечание. Пожалуйста, ознакомьтесь с обновлением в конце ответа, объявления в блоках стали действительными (но довольно сложными, если вы не используете строгий режим).
Вот одна причина:
var whatever;
if (some_condition) {
whatever = function() {
// Do something
};
}
else {
whatever = function() {
// Do something else
};
}
whatever();
В инициализации библиотеки вы можете увидеть такой код, который должен обрабатывать различия в реализации (например, различия между веб-браузерами, a'la IE attachEvent
и стандартным addEventListener
). Вы не можете сделать эквивалент с объявлением функции:
if (some_condition) {
function whatever() { // <=== DON'T DO THIS
// Do something
}
}
else {
function whatever() { // <=== IT INVALID
// Do something else
}
}
whatever();
... они не указаны в структурах управления, поэтому JavaScript-устройствам разрешено делать то, что они хотят, а разные двигатели сделали разные вещи. (Изменить: снова см. Примечание ниже, они указаны сейчас.)
Отдельно существует большая разница между
var whatever = function() {
// ...
};
и
function whatever() {
// ...
}
Первое - это выражение функции, и оно оценивается, когда код достигает этой точки в пошаговом выполнении контекста (например, в его функции или поэтапном выполнении глобального кода), Это также приводит к анонимной функции (переменная, относящаяся к ней, имеет имя, но функция не имеет значения, что имеет значение для помогает вашим инструментам помочь вам).
Вторая - это объявление функции, и она оценивается при входе в контекст, до выполняется любой пошаговый код. (Некоторые называют этот "подъем", потому что что-то дальше в источнике происходит раньше, чем что-то выше в источнике.) Функция также имеет собственное имя.
Итак, рассмотрим:
function foo() {
doSomething();
doSomethingElse();
console.log("typeof bar = " + typeof bar); // Logs "function"
function bar() {
}
}
тогда
function foo() {
doSomething();
doSomethingElse();
console.log("typeof bar = " + typeof bar); // Logs "undefined"
var bar = function() {
};
}
В первом примере с объявлением декларация обрабатывается до запуска doSomething
и другого поэтапного кода. Во втором примере, поскольку это выражение, оно выполняется как часть поэтапного кода, поэтому функция не определена выше (переменная определена выше, потому что var
также "поднят" ).
И завершение: на данный момент вы не можете сделать это в целом на веб-сайте клиентской стороны:
var bar = function foo() { // <=== Don't do this in client-side code for now
// ...
};
Вы должны это сделать, он называется выражением именованной функции, и это выражение функции, которое дает функции правильное имя. Но различные JavaScript-движки в разное время ошибались, и IE продолжал очень сильно ошибаться до самого недавнего времени.
Обновление для ES2015 +
Как и в ES2015 (иначе ES6), в спецификацию были добавлены объявления функций внутри блоков.
Строгий режим
В строгом режиме вновь заданное поведение прост и понятен: они привязаны к блоку, в котором они встречаются, и поднимаются на вершину.
Итак, это:
"use strict";
if (Math.random() < 0.5) {
foo();
function foo() {
console.log("low");
}
} else {
foo();
function foo() {
console.log("high");
}
}
console.log(typeof foo); // undefined