为啥我不能为具有相同名称的命名函数表达式中的变量赋值?
Posted
技术标签:
【中文标题】为啥我不能为具有相同名称的命名函数表达式中的变量赋值?【英文标题】:Why can’t I assign values to a variable inside a named function expression with the same name?为什么我不能为具有相同名称的命名函数表达式中的变量赋值? 【发布时间】:2014-07-24 03:53:22 【问题描述】:这是一个名为test
的命名函数表达式。在内部,我将123
分配给一个变量,也称为test
。然后记录test
。该函数在控制台中打印它的主体,但不是123
。这种行为的原因是什么?
(function test()
test = 123;
console.log( test );
());
我对函数执行的解释失败在哪里?
-
函数执行开始:
test
是引用函数本身的局部变量
局部变量test
被重新分配给编号123
console.log(test)
显示号码123
。
【问题讨论】:
***.com/questions/6318835/… 我不确定我们是否可以将其视为完全相同的副本。在这种情况下,有一个作业,而不仅仅是链接问题中的var test;
。
@dandavis 如果您还在这里,请在对 Kodlee 回答的评论中说“the name of the function is a "var" to the function...
”。以与声明参数相同的方式?如果是这种情况,那么函数名称是否受到某种保护?您可以更改参数的值,认为它们是“预先声明的”。
@Teemu:我不确定这个名字在底层是如何工作的。毫无疑问,函数名称有点特别,因为它似乎可以抵抗直接破坏,但我不知道“受保护”;你仍然可以“var test=123;”在函数内部,这是有道理的。 ecmaScript 规范检查可能会解释我们正在经历的现象。
javascript - Hoisting Issue的可能重复
【参考方案1】:
我相信ecma spec 的这一部分解释了这种行为。这特别涉及命名函数表达式
制作
FunctionExpression : 函数标识符 (FormalParameterListopt) FunctionBody
评估如下:
让 funcEnv 成为调用 NewDeclarativeEnvironment 并传递正在运行的执行上下文的词法环境作为参数的结果 设 envRec 为 funcEnv 的环境记录。 调用 envRec 的 CreateImmutableBinding 具体方法,传入 Identifier 的 String 值作为参数。 让闭包是创建一个新的函数对象的结果,如 13.2 中指定的,其参数由 FormalParameterListopt 指定,主体由 FunctionBody 指定。传入 funcEnv 作为 Scope。如果 FunctionExpression 包含在严格代码中或其 FunctionBody 是严格代码,则将 true 作为 Strict 标志传递。 调用 envRec 的 InitializeImmutableBinding 具体方法,传递 Identifier 的 String 值和闭包作为参数。 返回关闭。
在创建命名函数表达式的范围时使用CreateImmutableBinding
,将标识符(在本例中为test
)创建为不可变变量。这就是为什么分配给它不会改变它的值。
【讨论】:
相关的将是关于为什么这样做的讨论***.com/questions/15129504/… 非常感谢您的回答! @YuryTarabanko:它确实抛出一个Unhandled Error: Invalid assignment in strict mode
。也许试试(function() "use strict"; (function test() test = 123;()); ())
@RomanBelyaev 将var
添加到test
后,您将创建一个本地test
,而不是尝试重新分配不可变对象
@YuryTarabanko:这确实是 Chrome 中的一个错误。分配给arguments
时,它们会正确抛出。以上是关于为啥我不能为具有相同名称的命名函数表达式中的变量赋值?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Gatsby 的两个不同布局上的两个 StaticQuery 元素不能具有相同的名称?