twoLeftFeet
twoLeftFeet

Reputation: 720

Dojo "On" Checkbox Change Inside For Loop Scope Issue

I am working with Esri's Javascript Library 3.10, which is based on Dojo. I'm having an issue with scope, and despite trying different variations, I'm still having the same result. There is probably a much better way to do this, but I can't seem to figure it out.

I want to iterate through an object containing keys to a set of checkboxes, then assign an event handler using dojo/on to set a value based on the key, however, the key, "setting" inside the On(...) function is the same for all four iterations.

for (var setting in this.appSettings) {
    console.log(setting); //prints four different things
    if (this.hasOwnProperty(setting)) {
        this.checkboxHandles[setting] =
                On(this[setting], 'change', function (checked) {
                    //this.setValue(setting, checked)
                    console.log(setting) //prints the last 'setting' whenever checkbox is changed
                });
    }
}

So setting inside the On function is always the same value, even though the for loop is looping through four unique keys. First, why does this happen, and what are some suggestions to solving this?

Upvotes: 0

Views: 215

Answers (1)

Dimitri Mestdagh
Dimitri Mestdagh

Reputation: 44745

That's one of the JavaScriptessentials. Closures always refer to their outer scope variables by reference. This means that the event handler references to the setting variable. However, when the for-loop continues, the setting variable is referencing the next value in the array.

The solution to this problem is what we call an IIFE or an Immediately Invoked Function Expression.

If you replace the event handler with a function that returns a function, for example:

On(appSettings[setting], 'change', function (setting) {
  return function(checked) {
    //this.setValue(setting, checked)
    console.log(setting) //prints the last 'setting' whenever checkbox is changed       
  }
}(setting));

So, what happens here is that the setting variable is passed to the function wrapper, the advantage of this is that they are passed by value, not by reference.

So, if you access the setting variable from inside that function, it will refer to the locally scoped setting variable which is passed to that function.

How weird it may look, it works: http://jsfiddle.net/8sxqn53d/ An interesting slidedeck that explains this behavior can be found here.

Upvotes: 1

Related Questions