当您查看ECMAScript 6 specification时,我注意到了一些有趣的事情。
13 功能定义
语法
FunctionDeclaration : function Identifier ( FormalParameterListopt ) { FunctionBody }
FunctionExpression : function Identifieropt (FormalParameterListopt ) { FunctionBody }
这两个不同的声明类型进一步细分为以下语义定义:
生产
FunctionExpression : function ( FormalParameterListopt ) { FunctionBody }
的评估如下:返回创建新
Function
对象的结果,如中所述 13.2,参数由FormalParameterListopt
指定,正文由FunctionBody
指定。通过LexicalEnvironment
将执行上下文作为Scope运行。通过true
作为 如果Strict
代码中包含FunctionExpression
,则会strict
标记 或者FunctionBody
是strict
代码。
和
生产
FunctionDeclaration : function Identifier ( FormalParameterListopt ) { FunctionBody }
实例化如下 在声明绑定实例化(10.5)期间:返回创建新
Function
对象的结果,如中所述 13.2,参数由FormalParameterListopt
指定,正文由FunctionBody
指定。通过VariableEnvironment
将执行上下文作为Scope运行。传入true为Strict
如果FunctionDeclaration
代码中包含strict
或是否包含该标记 其FunctionBody
是strict
代码。
我是否正确地将此解释为声明
function foo(){};
被定义为基本上在“函数表”中声明,其中所有参数和变量在加载执行上下文时在堆栈上分配,而
function (){};
在解析执行之前基本上不存在,其所有变量和范围都是从有问题的本地执行上下文继承的?
或者用外行的术语来说,命名声明是预分配的,匿名声明是在“运行时”分配的。
答案 0 :(得分:4)
此处的重要性是不命名和未命名函数之间的区别,而是FunctionExpression
vs function foo() {...}
。
函数声明采用以下形式:
hoisted
注意函数关键字的位置,前面没有运算符。此样式为foo();
function foo() {console.log("Foo was called");}
到当前上下文的顶部,可在运行时使用,允许您说出以下内容:
function
另一方面,如果您将任何类型的运算符放在=
关键字前面,例如(
或foo(); // can't call it it here. `foo` exists due to hoisting, but it is `undefined`
var foo = function() {console.log("foo was called");}
foo();
,它就会成为函数表达式。在评估函数表达式之前,函数表达式不可用。
io.Reader
答案 1 :(得分:3)
A" 功能声明"是一个声明,而一个" FunctionExpression "是,表达。
函数声明语句和函数表达式之间的最大区别在于实例化函数对象,因此,此函数可以使用的范围。
函数标识符(" name")是语句的要求,对于表达式是可选的。
在这两种情况下,该函数仅在被调用时执行,但作为脚本静态分析的一部分进行解析 - 例如,如果函数表达式包含无效语句,则会抛出解析错误并且脚本赢了&#39 ; t执行。