javascript - 函数参数未声明变量中的 TDZ

标签 javascript function

当我尝试运行此代码片段中定义的 foo 函数时,我得到 ReferenceErrorb 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.

这不应引发引用错误。看起来这不是这里发生的事情。

有人可以解释一下编译器实际上做了什么以及它如何处理这段代码吗?

最佳答案

在每次函数调用时,引擎都会评估一些序言代码,其中包含形式参数,声明为 let 变量,并使用其实际值或默认表达式(如果提供)进行初始化:

var b = 3;

function foo( ) {
    let a = <actual param for a> OR 42;
    let b = <actual param for b> OR a + b + 5;
   // ..
}

由于函数中的 b 是词法的 (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 页:

For each String paramName in parameterNames, do

...Perform ! envRec.CreateMutableBinding(paramName, false).

关于javascript - 函数参数未声明变量中的 TDZ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53778917/

相关文章:

javascript - 如何在 JavaScript 中将日期转换为字符串?

javascript - 如何在JS中实现一条链?

c++ - 按字母顺序排列结构数组的问题。从 Z 到 A 有效,但不能从 A 到 Z

javascript - 如何格式化或 trim 数字以删除前缀 '0' ?

javascript - 内容未出现在我的图片幻灯片下方

javascript - 如何使用 focusout 在 jquery 中添加多个事件委托(delegate)

c# - C# 和 C++ 中的可选参数

javascript - 使用变量中定义的函数

python - 我应该用下划线开始一个辅助函数吗?

c - C99 标准中的默认参数提升