1

When using a "for in" loop to set a method, the proper method names are set, but the variables used in each function call are clobbered by the last set property.

Example Code

function colorLog() {
    var color = {
        graph: '#88A825',
        node: '#35203B',
        link: '#911146',
        error: '#AC2930',
        info: 'black'
    };

    var logger = {};
    for(var k in color) {
        logger[k] = function(msg) {
            console.log(color[k]);
            console.log("%c" + msg, "color:" + color[k] + ";font-weight:bold;");
        }
    }

    return logger;
}

var log = colorLog();

log.graph("Graph Says");
log.node("Node Says");
log.link("Link Says");
log.error("Error Says");
log.info("Info Says");

Output

black 
Graph Says 
black 
Node Says 
black 
Link Says
black 
Error Says 
black 
Info Says

What am I not understanding about scoping rules?

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
enjoylife
  • 3,801
  • 1
  • 24
  • 33
  • This is not about scoping rules. – u_mulder Sep 26 '14 at 18:05
  • 1
    @u_mulder: It's entirely about scoping rules. If the `for-in` created a new variable scope that included `k` on every iteration, which seems to be what's expected, there would be no issue. –  Sep 26 '14 at 18:09

1 Answers1

5

Each closure gets the same k so after all functions have been defined it points to the last key from color. The easiest way to solve it is creating a new one using an self-executing function:

for(var k in color) {
    logger[k] = (function(k) {
        return function(msg) {
            console.log(color[k]);
            console.log("%c" + msg, "color:" + color[k] + ";font-weight:bold;");
        };
    })(k);
}
ThiefMaster
  • 310,957
  • 84
  • 592
  • 636