Как объяснить различную реакцию на выполнение следующего кода в разных браузерах?
var func = function() { console.log('1'); };
function func() { console.log('2'); }
func();
При выполнении в Opera 36.0.2130.32 выдается ошибка:
"SyntaxError: Identifier 'func' has already been declared at
https://static.jsbin.com/js/prod/runner-3.35.11.min.js:1:13891 at
https://static.jsbin.com/js/prod/runner-3.35.11.min.js:1:10820"
При выполнении в Firefox 44.0.2 ошибка не выдается, и в консоль выводится значение "2".
Вот ссылка на jsbin: https://jsbin.com/hijobojawe/1/edit?js,console,output
Ответ
Хорошая демонстрация неочевидного момента т.н. "var hoisting". Дело в том, что на стадии инициализации все объявления переменных, которые могут быть где угодно в теле функции, перемещаются наверх, в то время, как их назначение остаётся на месте.
Было:
function x(){
// ..здесь много кода
var v = 'test'; // внезапно объявляем ещё одну переменную
// ..здесь дальше код
function f(){ /* тело ф-ии */ } // объявили функцию
}
Стало:
function x(){
function f(){ /* тело ф-ии */ } // объявили функцию
var v;
// ..здесь много кода
var v = 'test'; // внезапно объявляем ещё одну переменную
// ..здесь дальше код
}
Объявления функций так же могут находиться где-то ниже по коду внутри контекста, и при этом тоже «переезжают» вверх при исполнении. Причём, как пишут некоторые источники, становятся до объявления всех переменных.
Сначала function, потом var, потом v = 'test'
В вашем суперпримере ещё один вопрос: какое объявление function() сработает раньше – в правой части назначения переменной, или самостоятельное. Раньше сработает самостоятельное – function declaration. Назначение func = function(){..} выполнится в последнюю очередь.
Итак, сначала объявляется ф-я с 2, затем объявляется переменная func (и вызывает ошибку, т.к. с таким именем уже есть ф-я), а потом эта переменная получает значение ф-ии с 1. По-моему, это правильная реализация JS стандартов.
Тесты:
FireFox 45.0.1, ScratchPad, консоль FireBug: "1"
Chrome 49.0.2623.87 (64-bit), Uncaught SyntaxError: Identifier 'func' has already been declared
Safari 9.1 (11601.5.17.1), консоль: 1
Opera 34.0, консоль: 1
Opera 36.0, консоль: Uncaught SyntaxError: Identifier 'func' has already been declared
Комментариев нет:
Отправить комментарий