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?
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());
})();
}