为了账号安全,请及时绑定邮箱和手机立即绑定

JavaScript 匿名函数有哪几种执行方式?

JavaScript 匿名函数有哪几种执行方式?

萧十郎 2018-11-22 17:15:50
JavaScript 匿名函数有哪几种执行方式
查看完整描述

1 回答

?
杨__羊羊

TA贡献1943条经验 获得超7个赞

我们从规范出发,看看EcmaScript的上下文无关文法
参考《ECMA-262, 3rd edition, December 1999》。
ES3简单一些,ES6同理。
Program :
SourceElements

SouceElements :
SouceElement
SouceElements SourceElement

SouceElement :
Statement
FunctionDeclaration

Statement :
Block
VariableStatement
EmptyStatement
ExpressionStatement
IfStatement
IterationStatement
ContinueStatement
BreakStatement
ReturnStatement
WithStatement
LabelledStatement
SwitchStatement
ThrowStatement
TryStatement

ExpressionStatement :
[lookahead ∉ {{, function}] Expression ;

FunctionDeclaration :
function Identifier ( FormalParameterList[opt] ) { FunctionBody }

这几个产生式表明了以Program为根的语法树结构。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

(1)首先,“function(){}()”无法归约为CallExpression。
CallExpression
<- LeftHandSideExpression
<- PostfixExpression
<- UnaryExpression
<- MultiplicativeExpression
<- AdditiveExpression
<- ShiftExpression
<- RelationalExpression
<- EqualityExpression
<- BitwiseANDExpression
<- BitwiseXORExpression
<- BitwiseORExpression
<- LogicalANDExpression
<- LogicalORExpression
<- ConditionalExpression
<- AssignmentExpression
<- Expression
[失败了] <- ExpressionStatement
<- Statement
<- SourceElement
<- SourceElements
<- Program

失败的原因是,
Expression要想归约为ExpressionStatement,就不能以左大括号“{”或“function”开头。

(2)那么,我们只能认为“function(){}()”是由两部分构成的了。
program
-> SourceElements
-> SourceElements SourceElement
-> SourceElement SourceElement

把“funtion(){}”和“()”都分别向SourceElement归约。
然而,这又不行。

(3)“funtion(){}”无法归约为SourceElement。
因为,无论是先归约为Statement,还先归约为FunctionDeclaration都不行。
归约为Statement要求不能以function开头,(与上面的失败原因相同)
归约为FunctionDeclaration要求必须指定函数名。

(4)然而,我们又没有其他归约方法了,只能失败了。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

而加上符号以后,
例如“!function(){}()”,并不是以“function开头”的,
所以通过了Expression到ExpressionStatement的归约。
!function(){}()
<- ! function Identifier[opt] ( FormalParameterList[opt] ) { FunctionBody } Arguments
<- ! FunctionExpression Arguments
<- ! MemberExpression Arguments
<- ! CallExpression
<- ! LeftHandSideExpression
<- ! PostfixExpression
<- ! UnaryExpression
<- UnaryExpression
<- MultiplicativeExpression
<- AdditiveExpression
<- ShiftExpression
<- RelationalExpression
<- EqualityExpression
<- BitwiseANDExpression
<- BitwiseXORExpression
<- BitwiseORExpression
<- LogicalANDExpression
<- LogicalORExpression
<- ConditionalExpression
<- AssignmentExpression
<- Expression
<- ExpressionStatement
<- Statement
<- SourceElement
<- SourceElements
<- Program

同理可以推导(function(){}()),(function(){})()

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

值得指出的是,
“function(){}()”就算指定了函数名,也不行。
因为后面的“()”同样不能归约为SourceElement。

而“function f(){}(1)”就是合法的,
“function f(){}”归约为FunctionDeclaration,
而“(1)”可以归约为Expression,视为括号运算符,或称为分组运算符。
(Expression)
<- PrimaryExpression
<- MemberExpression
<- NewExpression
<- LeftHandSideExpression
<- PostfixExpression
<- UnaryExpression
<- MultiplicativeExpression
<- AdditiveExpression
<- ShiftExpression
<- RelationalExpression
<- EqualityExpression
<- BitwiseANDExpression
<- BitwiseXORExpression
<- BitwiseORExpression
<- LogicalANDExpression
<- LogicalORExpression
<- ConditionalExpression
<- AssignmentExpression
<- Expression



查看完整回答
反对 回复 2018-12-13
  • 1 回答
  • 0 关注
  • 517 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信