1

What is the correct way to set the corresponding values?
How to make this work with "for ... in".

The function I associate with self[state] appears to run after the loop with the latest value of states[state], not the one associated to it during the loop.

cssbtn = function(id, states, state){

  var self = document.getElementById(id);
  var states = states ||  {'off': '0px 0px', 'selected': '-20px 0px', 'selected2': '-40px 0px' };
  var state = state || 'off';

  for (state in states) {
    self[state] =  function (){
      alert(states[state]); //demo purposes
    }
  }

  self.onmouseover = function(evt){
    self.selected();
  }

  self.onmouseout= function(evt){
    self.off();
  }

  self.onclick= function(evt){
    self.selected2();
  }

  return self;
}

1 Answers1

1

One correct answer is:

self[state] = (function(i) { return function() { alert(i) } })(states[state]);

stumbled upon it from: How can one de-reference JavaScript variables when enclosing an outer scope

Is this the only way? A more obvious/elegant multi-lingual (not so javascript) approach?

Community
  • 1
  • 1
  • 1
    In future versions of javascript (and some browsers, if you allow for extensions) you can declare variables with "let" instead of "var" to use lexical scope that is not prone to the closures in for loops bug. Otherwise, you need to explicitely save state somewhere: this can be done either with objects or using functions like you did (although I prefer to create a named function like "make_alerter" instead of using an anon function) – hugomg Jun 18 '12 at 17:48
  • And of course, another possibility is using a "forEach" function from some library (similar to the Array foreach method found in modern JS environments). You lose access to early "break" and "return" but since the iteration is wrapped in a callback the index variable is properly closed and is not reused. – hugomg Jun 18 '12 at 17:55