Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Closures - Variable Change After Use

I am reading about closures on MDN and I can't understand something in the following code:

var test = 1;

function makeFunc() {
  var name = 'Mozilla';
  function displayName() {
    alert(name + ' ' + test);
  }
  return displayName;
}

//Create myFunction - test should still be set to 1 at this point
var myFunc = makeFunc();

test = 99999;

myFunc();

Why is Mozilla 99999 being printed instead of Mozilla 1 when the function was created while test was assigned 1? Shouldn't primitives by value types? I also don't think assignment gets hoisted, just declaration, pretty lost.

like image 652
VSO Avatar asked Oct 21 '25 04:10

VSO


2 Answers

From the article you linked:

The reason is that functions in JavaScript form closures. A closure is the combination of a function and the lexical environment within which that function was declared. This environment consists of any local variables that were in-scope at the time the closure was created.

Here, name is closed-over: It's a local variable at the time that the function was created. Though it's not a perfect analogy, you can think of it like the displayName function has an internal pointer to the stack frame containing all the local variables that were around when you defined the function. If you were to pass in name, you could see it being kept.

var test = 1;

function makeFunc(name) {
  function displayName() {
    alert(name + ' ' + test);
  }
  return displayName;
}

//Create myFunction - test should still be set to 1 at this point
var myFunc = makeFunc("one");
var myFunc2 = makeFunc("two");

test = 99999;

myFunc();   // combines closed-over name "one" with lexical scope test 99999
myFunc2();  // combines closed-over name "two" with lexical scope test 99999

Because test is in lexical scope, not a closed-over local variable, both makeFunc and makeFunc2 manipulate the same value in global scope, meaning that resetting test can manipulate the output even after you've created the closures.

like image 124
Jeff Bowman Avatar answered Oct 23 '25 19:10

Jeff Bowman


A closure does not merely capture a snapshot of test when it is created, but captures the entire variable itself. This means that whenever the function myFunc is called, it will print whatever the value of test is when it was called, not the value of test when the closure was created.

In other words, inside the closure, test is still a variable, not a value. That means it can be changed and manipulated however you want, and anything that uses it will see those changes.

So for your code, as soon as you call myFunc() on the last line, the runtime will evaluate the expression name + ' ' + test, and since test is now 99999, that's what you get.

like image 40
CRice Avatar answered Oct 23 '25 19:10

CRice



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!