1

A thing about closure. In these two snippets below I'm passing a function expression as a callback.

(In the first snippet) When calling back the function expression, I expect to see the anonymous function to close over def, but when I call second() instead of looking inside its "closure" for the variable first (where first is updatedValue), search and find first in the global variable environment, where first has the value oldValue.

function def(first="oldValue" , second=function(){ return first; }){ var first="updatedValue"; console.log('inside',first); console.log('function',second()); } //OUTPUT: inside updatedValue function oldValue 

On the other hand, if you don't declare first inside def, it second() console log updatedValue

function def(first="oldValue" , second=function(){ return first; }){ first="updatedValue"; // NOTE: removed the `var` here console.log('inside',first); console.log('function',second()); } //OUTPUT: inside updatedValue function updatedValue 

Can someone explain what's going on here?

1
  • You're not passing the closure as a parameter. You are defining a default initialiser for the parameter that gets used when nothing is passed. Commented Aug 1, 2018 at 12:49

1 Answer 1

1

As quoted from the ES specs here, using a default parameter creates a new scope in which the default parameters reside, then another scope in which the function body resides. That means that first refers to the variable in the enclosing default parameter scope, while var first shadows it in the functions scope.

Your code basically is the same as:

function def(_first, _second) { // Scope of the default parameters let first = _first ?? "default"; let second = _second ?? function(){ return first; }; (function() { // The functions scope var first = "updatedValue"; // scoped here console.log('inside',first); console.log('function',second()); })(); } 
Sign up to request clarification or add additional context in comments.

5 Comments

Hi @JonasWilms , could you please also explain why 2 separate scopes are created for the 2 parameters with default values, apart from the function body scope ? In all the examples in the link you shared stackoverflow.com/questions/44896829/…, only 1 scope is created for all parameters with default values. Also in this answer of yours parameters are declared using var but in the link you provided parameters are declared using let after de-sugaring, so how is var or let determined ?
@DhirenPunjabi this answer is slightly incorrect, technically there is only one environment record in which the default parameters are evaluated, though as parameters are only bound after being evaluated, later parameters are not visible in the evaluation of the default expression (c.f. 262.ecma-international.org/6.0/… 28.f)
So yeah, using one invoked function with let is a more accurate syntactic sugar.
As per this answer of yours to the question stackoverflow.com/questions/56301703/… , the parameter names also exist in the scope of the function body and if the parameters are declared by let (as per your above reply to my comment) then it might cause a redeclaration error. So it looks like parameters are declared with var by default and not let, for every javascript function. Please correct me if I'm wrong
@DhirenPunjabi parameters and let and const variables are three entirely different things with varying semantics, all of which can be described by environment records and bindings.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.