javascript - 函数参数未声明变量中的 TDZ
问题描述
当我尝试运行此代码段中定义的 foo 函数时,我得到一个ReferenceError
since b is not defined
。
var b = 3;
function foo( a = 42, b = a + b + 5 ) {
// ..
}
foo()
这看起来像一个 TDZ 错误,因为 b 已在外部范围中定义,但它还不能在函数签名中用作右侧值。
这是我认为编译器应该做的:
var b;
function foo(..) { .. }
// hoist all functions and variables declarations to the top
// then perform assignments operations
b = 3;
foo();
//create a new execution environment for `foo`
// add `foo` on top of the callstack
// look for variable a, can't find one, hence automatically create a
`var a` in the local execution environment and assign to it the
value `42`
// look for a `var b` in the global execution context, find one, use
the value in it (`3`) as a right-hand-side value.
这不应该引发 ReferenceError。看起来这不是这里发生的事情。
有人可以解释编译器实际上做了什么以及它如何处理这段代码吗?
解决方案
在每个函数调用中,引擎都会评估一些序言代码,其中包含形式参数,声明为let
vars 并使用它们的实际值或默认表达式进行初始化,如果提供的话:
var b = 3;
function foo( ) {
let a = <actual param for a> OR 42;
let b = <actual param for b> OR a + b + 5;
// ..
}
由于b
in 函数是词法 ( let
),因此无法在初始化之前访问其值。因此参考错误。
请注意,这是一个调用时错误,因此以下编译正常:
var b = 1
function foo(b=b) {
console.log(b)
}
当您实际调用该函数时会发生错误:
var b = 1
function foo(b=b) {
console.log(b)
}
foo()
并且仅当引擎实际评估错误的默认表达式时:
var b = 1
function foo(b=b) {
console.log(b)
}
foo(7)
ECMA 标准参考:FunctionDeclarationInstantiation,第 21 页:
对于 parameterNames 中的每个 String paramName,执行
...履行 !envRec.CreateMutableBinding(paramName, false)。
推荐阅读
- reactjs - 如何在 Flux 的 calculatestate 方法中设置新状态?
- hyperledger-fabric - IBM Blockchain Platform Nodejs 客户端应用程序无法提交事务:没有为要从中发现的 MSP 'org1Admin' 定义对等方
- javascript - 导出在 React 组件的 fetch() 函数中的 then() 方法中创建的变量
- regex - RegEx.Replace 函数限制返回的字符
- c# - 如何在 C# 中使用 LINQ 中的 if 条件
- logical-operators - 简化逻辑表达式
- java - 在 EDT 线程中创建 JFrame 实例是不好的做法吗?
- blazor - 使用 ASP.net Core 托管模型了解 Blazor 程序集
- jenkins - 如何列出 Jenkins 中的所有管道作业?
- kubernetes - kubernetes 使用环境变量来拉取图像