在 ECMAScript 2015 之前,函数参数被视为函数作用域中的变量。这意味着对于每个参数,都会创建一个新的变量,可以在函数内部使用。然而,在 JavaScript 中,存在一个被称为“暂时性死区(TDZ)”的概念,即在变量被声明之前,无法在代码中访问该变量。
ECMAScript 2015 引入了块作用域变量和常量的概念,并且函数参数也变成了块作用域的变量。这意味着,在函数参数被声明之前,它们受到 TDZ 的限制,无法在函数内部访问。
然而,在 ECMAScript 2021 中,函数参数引入的 TDZ 规则发生了一些更改,这可能会导致一些令人惊讶的结果。
更改的规则
在 ECMAScript 2021 中,函数参数的 TDZ 规则被调整为仅适用于具有初始值的参数。如果参数没有初始值,则可以在函数内部访问它们,而不会遭遇 TDZ 问题。
这意味着在以下情况下,函数参数不再受 TDZ 限制:
function foo(x, y = x) { return [x, y]; } foo(1); // [1, 1]
在这里,由于 y
具有初始值并使用 x
进行了初始化,因此我们可以在函数内部访问 y
,并返回正确的结果。
相反,如果我们省略了 y
的初始值,则会遇到 TDZ 问题:
function bar(x, y = z) { return [x, y]; } bar(1); // 抛出未定义的引用错误
在这里,我们试图使用 z
来初始化未给定初始值的 y
,因此会遭遇 TDZ 问题。
学习与指导
随着函数参数 TDZ 规则的更改,我们需要更加谨慎地处理参数和默认值。如果必须在函数参数中使用 TDZ 变量,则需要确保它们具有初始值,以避免遭遇意外的错误。
此外,在使用默认值时,应保持代码的简单和明确。如果可能,尽量避免嵌套默认值,因为这可能会导致更多的问题。
-- -------------------- ---- ------- -- ------ -------- ----- - -- - - - - -- - - - - -- - ------ --- -- --- - ------ -- --- -- -- -- ----- -------- ------ -- -- - - - - -- -- - - - -- - - -- - - - -- - - -- ------ --- -- --- - ------ -- --- -- --
这个例子展示了两种不同的方式来处理参数和默认值。第一种方式嵌套了默认值,可能导致代码更难以理解和调试。第二种方式使用了空值合并运算符(nullish coalescing operator),并明确地给每个参数赋予了一个值,使代码更加清晰和易于维护。
最后,尽管函数参数的 TDZ 规则发生了变化,但是我们仍然需要小心谨慎地处理函数参数和默认值,以确保代码的正确性和可读性。
结论
ECMAScript 2021 更改了函数参数引入的 TDZ 问题,仅在具有初始值的情况下才适用于 TDZ 规则。这需要我们更谨慎地处理参数和默认值,并避免嵌套默认值、正确使用空值合并运算符等等。通过遵守这些最佳实践,我们可以编写出更加清晰、可靠的代码。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/676d253e82fcee791c65042f