const show1 = function(x, y = () => {x = 2; return x;}) {
let x = 3;
console.log(y());
console.log(x);
};
show1();
const show2 = function(x, y = () => {x = 2; return x;}) {
x = 3;
console.log(y());
console.log(x);
};
show2();
const show3 = function(x, y = () => {x = 2; return x;}) {
var x = 3;
console.log(y());
console.log(x);
};
show3();
输出
show1: Uncaught SyntaxError: Identifier 'x' has already been decalred;
show2: 2 2
show3: 2 3
问题
我被告知存在一个临时死区,其中参数变量被声明和初始化。请参阅https://exploringjs.com/es6/ch_variables.html#sec_parameters-as-variables 。所以这里有两个作用域,一个是参数作用域,另一个是函数作用域。
- 从 show1 中的错误来看,我认为该函数中已经声明了一个
x
变量。 - 根据Redeclaring a javascript variable 。重新声明不会对
x
执行任何操作(使用var
)。为什么show2
和show3
的结果不同。
我在这里发布了同样的问题If the variables are already declared at the beginning of function execution被掩盖为重复。但我找不到任何有用的东西来解决我的疑问。
最佳答案
show1
抛出错误,因为使用 let
或 const
声明的变量 cannot have any other variables with the same name在该 block 中初始化(无论是在参数列表中还是使用 const
/let
/var
)。
默认参数引用的变量具有奇怪的作用域规则。每个参数本质上都会创建另一个可以在其中定义该参数名称的 block 。所以
const show3 = function(x, y = () => { x = 2; return x; }) {
有点像(请原谅伪代码):
const show3 = < function >{
let x = firstArg;
{
let y = secondArg === undefined ? () => { x = 2; return x; } : secondArg;
{
// function body
当您简单分配参数列表中的变量名称时,该参数将被覆盖。但是,当您使用语法初始化一个新变量(使用var
)时,您已经为该变量名称创建了另一个绑定(bind),这只是在函数体内可见:
const show3 = {
let x = firstArg;
{
let y = secondArg === undefined ? () => { x = 2; return x; }
// the x referenced in the above line references the outer x, the first argument
{
// function body
// since "var x" is declared here, any references to "x" in this block
// will only reference the inner x
// but not the outer x
var x = /* something */
因此,您的 show2
正在将函数体第一行中名为 x
的参数重新分配给 3。相反,show3
正在创建一个与 x
同名的新变量绑定(bind),而 y
函数的引用to x
正在引用参数 x
,这是不同的。
关于javascript - 如果使用 var 重新声明会对现有变量产生影响,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58217477/