Определение eval как формального параметра вызова конструктора Function. Разве это не должно вызывать синтаксическую ошибку в коде строгого режима?

В спецификации указано:

Использование в коде строгого режима идентификаторов eval или arguments в качестве идентификатора объявления функции или выражения функции или в качестве формального имени параметра (13.1) является SyntaxError. Попытка динамически определить такую ​​функцию строгого режима с помощью конструктора Function (15.3.2) вызовет исключение SyntaxError.

Источник: http://es5.github.com/C.html#C (последний пуля)

Следовательно, это вызывает синтаксическую ошибку (в Firefox, Chrome и Opera):

(function () {
    'use strict';

    var f = function ( eval ) {};
})();

Текущая демонстрация: http://jsfiddle.net/v8Ff4/

Однако это не вызывает синтаксическую ошибку:

(function () {
    'use strict';

    var f = new Function( 'eval', '' );
})();

Текущая демонстрация: http://jsfiddle.net/v8Ff4/1/

Насколько я понимаю, этот второй блок кода должен вызывать синтаксическую ошибку. Должен ли? И если да, то почему нет?


person Šime Vidas    schedule 10.12.2011    source источник
comment
Подождите минутку, может быть, поскольку функция new Function(...) выполняется в глобальном коде (ее область действия является глобальной областью действия), к ней не применяется строгое правило использования. Это оно?   -  person Šime Vidas    schedule 10.12.2011
comment
Я не знаю. Мне это кажется странным, поскольку строгий режим ограничен лексически, и если вы добавите 'use strict' на глобальном уровне, создание такой функции должно наследовать строгий режим. Поскольку формальный параметр eval находится в новой среде функции (он не является глобальным), кажется, что вы должны получить ошибку.   -  person RightSaidFred    schedule 11.12.2011
comment
При этом: var f = new Function( 'eval', '"use strict";' ); вы получаете ошибку. Но не с этим: "use strict"; var f = new Function( 'eval', ';' ); Кажется, это неправильно.   -  person RightSaidFred    schedule 11.12.2011
comment
Этот запуск глобально: eval( 'var f = function( eval ) { ; }' ); также дает вам ошибку.   -  person RightSaidFred    schedule 11.12.2011
comment
@RightSaidFred Я понял это. Такое поведение является правильным и соответствует стандарту. Я опубликую подробный ответ позже... (Я могу уведомить вас, если вы хотите)   -  person Šime Vidas    schedule 11.12.2011
comment
@RightSaidFred Я опубликовал свой ответ.   -  person Šime Vidas    schedule 12.12.2011
comment
@gsnedders Оказалось, причина была не в этом...   -  person Šime Vidas    schedule 12.12.2011


Ответы (1)


Итак, я собираюсь ответить на свой вопрос здесь (так как я понял это).

Моя первоначальная предпосылка заключалась в том, что оба блока кода эквивалентны. Так что это

var f = function ( eval ) {};

эквивалентно

var f = new Function( 'eval', '' );

Однако это не так. Есть различия. Создание объекта-функции из нотации объявления/выражения функции описано в Главе 13.2 Создание объектов-функций. С другой стороны, создание объекта функции из вызова конструктора new Function описано в главе 15.3. 2.1 новая функция (p1, p2, … , pn, body). Так что здесь работают разные алгоритмы.

Конкретная часть, имеющая отношение к этому вопросу, - это часть, которая определяет строгость созданного функционального объекта.

Выражения функций

Строгость функционального объекта, созданного с помощью функционального выражения, определяется в семантике создания FunctionExpression в начале главы 13:

Передайте true как флаг Strict, если FunctionExpression содержится в строгом коде или если его FunctionBody является строгим кодом.

Таким образом, объект функции будет строгим, если выполняется любое из этих условий:

  • выражение функции содержится в строгом коде
  • тело функции выражения функции является строгим кодом

так, например, функция f является строгой в обоих приведенных ниже примерах.

Пример 1:

(function () {    
    var f = function () {
        'use strict';
        return 'I am strict!';
    }    
})();

Пример 2:

(function () {
    'use strict';    
    var f = function () {
        return 'I am strict!';
    }    
})();

Вызов конструктора функции

Строгость объекта функции, созданного с помощью вызова конструктора функции, определяется на шаге 9 алгоритма из главы 15.3.2.1 (уже ссылка выше):

Если тело является кодом строгого режима (см. 10.1.1), тогда пусть strict будет истинным, иначе пусть strict будет ложным.

Таким образом, не имеет значения, содержится ли вызов new Function в строгом коде. Чтобы создать строгую функцию с помощью этого шаблона, необходимо явно определить строгость в теле функции (это последний аргумент, передаваемый конструктору.

new Function ( 'a, b', 'return a + b;' ); // not strict
new Function ( 'a, b', '"use strict"; return a + b;' ); // strict
person Šime Vidas    schedule 11.12.2011
comment
Да, вы поняли. 10.1.1 Код функции, который предоставляется в качестве последнего аргумента встроенному конструктору Function, является строгим кодом функции, если последний аргумент... начинается с директивы Prologue, которая содержит директиву Use Strict. Это ничего не говорится о том, что он содержится в коде строгого режима. - person RightSaidFred; 12.12.2011