【问题标题】:Why can't the name of a function expression be reassigned?为什么不能重新分配函数表达式的名称?
【发布时间】:2019-11-14 22:07:38
【问题描述】:

为什么后面的sn-p会报错?

"use strict";
(function a() {
  console.log(typeof a); // function
  console.log(a = 0); // error
})();

为什么这个 sn-p 不抛出错误?

"use strict";
(function() {
  function a() {
    console.log(a = 0); // 0
  }
  return a;
})()();

为什么立即返回函数会抛出错误?

"use strict";
(function() {
  return function a() {
    console.log(a = 0); // error
  };
})()();

函数表达式是唯一发生这种情况的情况吗?为什么不能重新分配?

【问题讨论】:

  • 在第一个示例中,a 是函数的名称,但它不是环境中的实际绑定。与您执行 foo = function bar() {} 相同 - 您不能调用 bar(),因为该标识符不存在。
  • @VLAZ 但是你可以在第一个例子中在a 中调用a()...
  • @deceze 啊,真的。我以某种方式完全误读了第一个示例,因为它试图在它之外重新分配 a...
  • 为什么第二个例子没有抛出错误:因为它是一个函数声明而不是一个函数表达式。命名函数表达式对于在它们内部使用的名称有奇怪和特殊的规则。函数声明只是其范围内的变量。
  • 是的,它是一个命名函数表达式的东西。和class 类内部的东西,现在(class X { constructor() { X = 0; } } new X(); /* fails */ X = 0; /* sets */)。为什么?因为规范是这么说的。

标签: javascript function


【解决方案1】:

因为命名 FunctionExpressions 的行为方式与 FunctionDeclarations 的行为方式不同

规则到create a named FunctionExpression are:

FunctionExpression:functionBindingIdentifier(FormalParameters){FunctionBody}

  1. 让 scope 为正在运行的执行上下文的 LexicalEnvironment。
  2. 设 funcEnv 为 NewDeclarativeEnvironment(scope)。
  3. 设 envRec 为 funcEnv 的 EnvironmentRecord。
  4. 让名称为 BindingIdentifier 的 StringValue。
  5. 执行 envRec.CreateImmutableBinding(name, false)。
  6. 设闭包为 FunctionCreate(Normal, FormalParameters, FunctionBody, funcEnv)。
  7. 执行 MakeConstructor(闭包)。
  8. 执行 SetFunctionName(closure, name)。
  9. 将closure.[[SourceText]]设置为FunctionExpression匹配的源文本。
  10. 执行 envRec.InitializeBinding(name,closure)。
  11. 返回关闭。

重要的是 .5 确实使函数的名称成为immutable binding


  • 在第一种情况下,您尝试重新分配此不可变绑定它会抛出

  • 然而,在第二种情况下,您命名的函数不是 FunctionExpression,而是一个 FunctionDeclaration,它具有different behavior

    李>
  • 在最后一种情况下,它是一个 FunctionExpression,在这方面与第一种情况相同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-21
    • 2011-09-13
    • 1970-01-01
    • 2018-02-16
    • 2014-07-24
    • 2022-07-23
    • 2015-12-26
    • 1970-01-01
    相关资源
    最近更新 更多