(如果函数体处于严格模式,函数eval(){})会抛出语法错误?

Šim*_*das 14 javascript theory

为什么这段代码会抛出错误?

// global non-strict code
(function eval () { 'use strict'; });
Run Code Online (Sandbox Code Playgroud)

现场演示: http ://jsfiddle.net/SE3eX/1/

所以,我们这里有一个命名函数表达式.我想明确指出这个函数表达式出现在非严格的代码中.如您所见,它的函数体是严格的代码.

严格的模式规则在这里:http://ecma-international.org/ecma-262/5.1/#sec-C

相关的子弹就是这个(它是列表中的最后一个):

它是一个SyntaxError,在严格模式代码中使用标识符eval或arguments作为FunctionDeclaration或FunctionExpression的标识符或作为形式参数名称(13.1).尝试使用Function构造函数(15.3.2)动态定义此类严格模式函数将引发SyntaxError异常.

请注意,如果函数声明/表达式本身出现在严格的代码中,则此规则仅适用,在上面的示例中不会出现这种情况.

但它仍然会抛出错误?为什么?

Dav*_*nco 10

§13.1概述了像你这样的案件应该发生的事情:

  • 如果任何Identifier值在严格模式FunctionDeclaration或FunctionExpression的FormalParameterList中出现多次,则为SyntaxError.
  • 如果标识符"eval"或标识符"arguments"出现在严格模式FunctionDeclaration或FunctionExpression的FormalParameterList中,则为SyntaxError.
  • 如果标识符"eval"或标识符"arguments"作为严格模式FunctionDeclaration或FunctionExpression的标识符出现,则为SyntaxError.

强调我的.因此,您的严格模式函数的标识符evala SyntaxError.游戏结束.


要了解上面为什么是"严格模式函数表达式",请查看§13(函数定义)中的语义定义:

生产
FunctionExpression:function Identifier opt ( FormalParameterList opt ) { FunctionBody } 的评估如下:

  1. 返回使用FormalParameterListopt指定的参数和FunctionBody指定的主体创建13.2中指定的新Function对象的结果.将正在运行的执行上下文的LexicalEnvironment作为Scope传递.如果FunctionExpression包含在严格代码中或者其FunctionBody是严格代码,则传入true作为Strict标志.

强调我的.上面显示了函数表达式(或声明)如何变得严格.它所说的(用简单的英语)是一个FunctionExpressionstrict两种情况:

  1. 它是从use strict上下文中调用的.
  2. 它的功能体开始于use strict.

你的困惑源于以为只有函数体strict,而事实上,整个函数表达式strict.您的逻辑虽然直观,但并不是JS的工作原理.


如果您想知道为什么ECMAscript以这种方式工作,那就非常简单了.假设我们有这个:

// look ma, I'm not strict
(function eval() {
     "use strict";
     // evil stuff
     eval(); // this is a perfectly legal recursive call, and oh look...
             // ... I implicitly redefined eval() in a strict block
     // evil stuff
})();
Run Code Online (Sandbox Code Playgroud)

值得庆幸的是,上面的代码将抛出,因为整个函数表达式被标记为strict.