Является ли это ошибкой 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.