Дефиниране на eval като формален параметър на извикване на конструктор на функция. Не трябва ли това да хвърля синтактична грешка в кода на строг режим?

Спецификацията гласи:

Синтаксична грешка е използването в кода на строг режим на идентификаторите eval или аргументите като идентификатор на FunctionDeclaration или FunctionExpression или като официално име на параметър (13.1). Опитът за динамично дефиниране на такава функция в строг режим с помощта на конструктора 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, тяло). Така че тук работят различни алгоритми.

Специфичната част, която има отношение към този въпрос, е частта, която определя строгостта на създадения функционален обект.

Функционални изрази

Строгостта на функционален обект, създаден чрез функционален израз, е дефинирана в семантиката на продукцията 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 (вече свързана по-горе):

Ако body е код на строг режим (вижте 10.1.1), тогава нека strict да е true, в противен случай нека strict да е false.

Така че дали извикването на 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 Функционалният код, който се доставя като последен аргумент на вградения конструктор на функция, е строг функционален код, ако последният аргумент... започва с пролог на директива, който съдържа стриктна директива за използване. Той не казва нищо за това, че се съдържа в код на строг режим. - person RightSaidFred; 12.12.2011