将“eval”定义为Function构造函数调用的形式参数。不应该在严格模式代码中抛出语法错误吗?

时间:2011-12-10 18:49:24

标签: javascript eval syntax-error strict-mode

规范声明:

  

在严格模式代码中使用标识符是一个SyntaxError   eval或arguments作为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/

据我所知,第二个代码块应该抛出语法错误。应该是?如果是的话,为什么不呢?

1 个答案:

答案 0 :(得分:2)

所以,我将在这里回答我自己的问题(因为我已经弄明白了)。

我最初的前提是两个代码块都是等价的。这就是这个

var f = function ( eval ) {};

相当于

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

但事实并非如此。有区别。从函数声明/表达式表示法创建函数对象在Chapter 13.2 Creating Function Objects中定义。另一方面,new Function构造函数调用中创建的函数对象在Chapter 15.3.2.1 new Function (p1, p2, … , pn, body)中定义。所以这里有不同的算法。

与此问题相关的特定部分是定义所创建的函数对象的严格性的部分。

功能表达

通过函数表达式创建的函数对象的严格性在第13章开头的生产 FunctionExpression 的语义中定义:

  

如果包含FunctionExpression,则将true作为Strict标志传入   在严格的代码中或者如果它的FunctionBody是严格的代码。

因此,如果满足以下任一条件,函数对象将是严格的:

  • 函数表达式包含在严格的代码中
  • 函数表达式的函数体是严格代码

因此,例如,函数f在以下两个示例中都是严格的。

示例1:

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

示例2:

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

函数构造函数调用

通过Function构造函数调用创建的函数对象的严格性在第15.3.2.1节(上面已经链接)的算法的步骤9中定义:

  

如果body是严格模式代码(见10.1.1),那么let strict为true,否则let strict为false。

因此,new Function调用是否包含在严格的代码中无关。要通过此模式创建严格函数,必须在函数体中明确定义严格性(这是提供给构造函数的最后一个参数。

new Function ( 'a, b', 'return a + b;' ); // not strict
new Function ( 'a, b', '"use strict"; return a + b;' ); // strict