Страницы

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

среда, 3 апреля 2019 г.

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

Как объяснить различную реакцию на выполнение следующего кода в разных браузерах?
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

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

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