Является ли это ошибкой Chrome или я использую "use strict" и eval invalid?
Этот код работает с предупреждениями "ok" во всех браузерах, кроме Chrome:
eval("var outer = 0; function test() {'use strict'; outer = 1; } test(); alert('ok');");
(Попробуйте на jsfiddle).
Все, что я делаю, ссылается на внешнюю переменную из функции 'use strict'
, все в контексте eval
. Chrome говорит
Uncaught ReferenceError: outer is not defined
Примечание. Первоначально я столкнулся с этим при использовании devtool: 'eval'
в Webpack.
Ответы
Ответ 1
Чтобы упростить задачу: http://jsfiddle.net/rokkkjcs/6/
eval("var outer=0;");
function test() {'use strict'; outer = 1; }
test();
alert('ok');
И объяснение:
Нестрогий код может использовать функцию eval для добавления новых переменных в окружающую область. До поддержки встроенного JSON в браузерах 'eval обычно (и небезопасно) использовался для построения объектов из строк. Затем построенные объекты стали частью окружающей сферы. В строгом режиме "eval не может вводить новые переменные. При выполнении в строгом режиме следующий фрагмент кода не будет вводить переменную" bar" в окружающий объем. Примечание: если функция, содержащая 'eval, выполняется в строгом режиме, тогда код внутри функции eval также выполняется в строгом режиме.
Дополнительная информация: http://cjihrig.com/blog/javascripts-strict-mode-and-why-you-should-use-it/
Ответ 2
Фактически eval создает переменные или изменяет переменные в области, где она определена, независимо от того, используете ли вы val или нет. Или, другими словами, по умолчанию у него нет собственной области видимости.
Итак, когда вы это делаете
eval("var outer = 0;");
console.log(outer); //0
вы создаете переменную во внешней области. Удивительно, но это работает так же и в хроме - и не имеет значения, используется ли window.onload или нет.
Чтобы у eval была собственная область действия, вы должны сделать следующее:
eval("'use strict'; var outer = 0;");
console.log(outer); //Uncaught ReferenceError: outer is not defined
Теперь для eval существует отдельная область.
С "use strict" в eval ваш код будет работать в chrome и не позволит переопределять переменные за пределами eval.
eval("'use strict'; var outer = 0; function test() {'use strict'; outer = 1; } test(); alert('ok');");
Итак, эта часть отвечает, как избежать ошибки.
Вторая часть, в которой я очень заинтересована, но не смогла найти ответ самостоятельно.
Возникает вопрос: почему ваш код выдает ошибку в chrome, пока это работает в chrome (что означает, что создается глобальная переменная):
window.onload = function() {
eval("var outer = 0; function test(){console.log(outer); } test();");
}
А также почему это происходит только с window.onload
.