Страницы

Поиск по вопросам

пятница, 31 января 2020 г.

Различная реакция на переопределение идентификатора в браузерах Opera и Firefox

#javascript #ecmascript


Как объяснить различную реакцию на выполнение следующего кода в разных браузерах?

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
    


Ответы

Ответ 1



Хорошая демонстрация неочевидного момента т.н. "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

Ответ 2



Я так понимаю, что должно быть вообще "1". В моем ИЕ как раз выводится единица.Что тут происходит? При выполнении скрипта существует 2 стадии. Стадия инициализации и стадия выполнения. Function Declaration (2 строка) происходит на стадии инициализации. Далее по-ходу выполнения скрипта - тело функции переписывается в function expression (1 строка), которые как раз выполняются на стадии выполнения. В итоге мы должны видеть (И видим в ИЕ) единицу.А то, что мы видим на практике - видимо различия реализации JS движков, у каждого производителя он свой. Мы видим, что Opera(и Хром) не дают переписать объявленную функцию. Firefox просто игнорирует перезапись, а IE спокойно перезаписывает. Почитать.

Комментариев нет:

Отправить комментарий