user2908321
user2908321

Reputation:

Why is this not a javascript closure?

I have 2 buttons: button1 and Button2. And I have the following code:

$(document).ready(function() {
  var message = "hello 1";
  $("#button1").on("click", function() {
    alert(message);
  });
  message = "hello 2";
  $("#button2").on("click", function() {
    alert(message);
  });
});

When I click on button1 I am getting "hello 2". I thought this would be closure and I will be getting "hello 1". Please help

Upvotes: 0

Views: 60

Answers (4)

Simon Boudrias
Simon Boudrias

Reputation: 44589

Scope in JavaScript is hold in a function. Each time you declare a function, it creates a scope (a closure). So yes, you created a closure, but the behavior you see is the one you should expect.

Here, message is scoped to the document ready callback. And each click handlers refers to this same scope when searching for the message variable value. As so, the message variable hold the same value at the time click events are triggered.

To see it, just check the scope as a chain:

"document ready"
  - var message (it is declared here and can only have one value at a given time)
  - "#button1 click handler"
    - no var (so it'll search the parent scope for the value)
  - "#button2 click handler"
    - no var

Each scope then refers to their parent scope to search for a variable not belonging to its own scope.

Upvotes: 3

Jeff
Jeff

Reputation: 123

While those are closures, both of the closures are referencing the message variable. When the #button1 on click function is called (when the user clicks on it), it uses the current value of the message variable, which is changed to "hello 2" before the end of your ready function.

You can avoid this by not re-using the same variable for different messages, as in the below example:

$(document).ready(function() {
  var message1 = "hello 1";
  $("#button1").on("click", function() {
    alert(message1);
  });
  var message2 = "hello 2";
  $("#button2").on("click", function() {
    alert(message2);
  });
});

Upvotes: 0

Barmar
Barmar

Reputation: 780852

A closure doesn't save the value of a variable, it just saves a particular local variable instance. So the assignment message = "hello 2" updates the variable that is in both closures.

Upvotes: 3

Marc B
Marc B

Reputation: 360602

You're defining a global variable message, and assigning values to it. When the .on('click'... stuff is executed, the NAME of the message variable is embedded in those freshly-created functions, not its value at-the-the-time-the-function-is-defined.

So when you do actually click on those buttons, JS takes the variable NAME that was embedded in the functions, looks up its CURRENT value (which is 'hello 2'), and there's your output.

If you were impossibly quick and your browser running relatively slowly, you could POSSIBLY manage to click on your #button1 and get hello 1, IF the JS engine hasn't actually managed to actually start executing that message = 'hello 2'; line yet. But that's essentially impossible to do. You're not that quick.

Upvotes: 1

Related Questions