3

See this

let foo = 'outer';

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

bar(); //outer

I want to know why the output is 'outer' rather than 'inner'. I know JavaScript has lexical scope. This output makes me feels like that the function x => foo is defined out of function bar

maazadeeb
  • 5,922
  • 2
  • 27
  • 40
Messiah
  • 63
  • 5
  • 1
    do you understand that without the `let` in `let foo = 'inner';` you'd get what you expect, right? – Jaromanda X May 28 '17 at 06:03
  • 2
    It doesn’t make much sense for default argument values to have access to the function’s scope, so they don’t. – Ry- May 28 '17 at 06:06
  • 2
    Default parameter expressions are evaluated in a special scope which includes other parameters (and the function itself), so for example `function bar(foo, func = x => foo, otherFunc = bar)` would work to default `func` to a function returning the parameter `foo`, and `otherFunc` to the function itself, but of course that special scope does **not** include variables internal to the function. –  May 28 '17 at 06:19
  • `let` defines a new local variable that hides/overrides any previous definition in a higher scope by that name. Furthermore, `let` does not take effect until the line of code that the `let` statement is on. As such, the `foo` reference in your default function parameter assignment is the outer `foo`, not the inner `foo` because it is defined BEFORE the `let` statement that defines a new value for `foo`. References to variables are lexical. The lexical reference of `foo` in the default argument is the outer `foo`. Or put differently, default arguments don't have access to the function's scope. – jfriend00 May 28 '17 at 06:33
  • Just wanted to point out that it prints 'inner' when using Babel and 'outer' otherwise. [Seeing the code](https://gist.github.com/maaz93/06c05d0577dbf1eb8c9c9fa9616d2000) that Babel transpiles to, it's pretty evident why. – maazadeeb May 28 '17 at 06:46
  • 1
    @MaazSyedAdeeb Infact it's a bug in Babel,you can see this https://github.com/babel/babel/issues/4173 – Messiah May 28 '17 at 07:15

1 Answers1

0

I know js has lexical scope, This output makes me feels like that the function x => foo is defined out of function bar

Not exactly. It's in-betweeen: in the parameter declaration, which has its own scope with access to the other parameters but not the body. The default initialiser basically desugars to

let foo = 'outer';
function bar() {
  var func = arguments[0] === undefined ? x => foo : arguments[0];
  {
    let foo = 'inner';
    console.log(func());
  }
}
bar(); // outer
Bergi
  • 630,263
  • 148
  • 957
  • 1,375