函数默认参数中的一些问题?

3

请看这个

let foo = 'outer';

function bar(func = x => foo) {
  let foo = 'inner';
  console.log(func()); 
}

bar(); //outer

我想知道为什么输出结果是“outer”而不是“inner”。我知道JavaScript具有词法作用域。这个输出让我感觉像函数x => foo是在函数bar之外定义的。

1
你明白在 let foo = 'inner'; 中没有使用 let 会得到你预期的结果吗? - Jaromanda X
2
默认参数值没有访问函数作用域的必要,因此它们不会访问。 - Ry-
2
默认参数表达式在一个特殊的作用域中进行求值,该作用域包括其他参数(以及函数本身),因此例如 function bar(foo, func = x => foo, otherFunc = bar) 可以将 func 默认为返回参数 foo 的函数,并将 otherFunc 默认为函数本身,但是当然这个特殊作用域不包括函数内部的变量。 - user663031
let 定义了一个新的本地变量,该变量会隐藏/覆盖先前在更高作用域中使用同名变量的定义。此外,let 只有在 let 语句所在的代码行之后才生效。因此,在默认函数参数赋值中的 foo 引用是外部的 foo,而不是内部的 foo,因为它是在定义一个新值的 let 语句之前定义的。变量的引用是词法的。默认参数中 foo 的词法引用是外部的 foo。或者换句话说,默认参数无法访问函数的作用域。 - jfriend00
只是想指出,当使用Babel时,它会打印“inner”,否则会打印“outer”。通过查看Babel转译的代码,很明显为什么会这样。查看代码 - maazadeeb
1
@MaazSyedAdeeb 实际上这是Babel的一个bug,你可以在这里查看 https://github.com/babel/babel/issues/4173 - Messiah
1个回答

0
我知道JS有词法作用域,这个输出让我感觉像是函数 x => foo 是在函数 bar 外定义的。
不完全是这样。它是介于两者之间的:在参数声明中,它有自己的作用域,可以访问其他参数但不能访问函数体。默认初始化器 基本上是解糖
let foo = 'outer';
function bar() {
  var func = arguments[0] === undefined ? x => foo : arguments[0];
  {
    let foo = 'inner';
    console.log(func());
  }
}
bar(); // outer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接