0

I'm trying to prototype a custom logger with different levels (debug, info, warn...) each one with different properties like color, name etc.

What I'm trying to do is build dynamically all those levels, getting them from a Hashmap where I store all the properties. So for example I have my custom logger object with logger.debug('test'), logger.info('text), and so on. You get the idea.

BUT, I'm having problems with this particular code:

var MyLogger = function(opts) {
    this.level = opts.level || 0
    this.loggers = {}

    var self = this

    for (l in LEVELS) {
        this.addLogger(l, new loggerOutput(LEVELS[l]))
        this[l] = function(message) {
            self.getLogger(l).output(message)
        }
    }
}

The problem is with self.getLogger(l), as it always point to my last logger (ERROR). If I replace the variable with a static string, it works: self.getLogger('info')

The workaround is to prototype by hand all loggers, and obviosly that works, but I was expecting to find a better solution:

MyLogger.prototype = {
    debug: function(message) {
        this.getLogger('debug').output(message)
    },
    info: function(message) {
        this.getLogger('info').output(message)
    }
        ...
}

Thank you in advance.

ajm
  • 19,795
  • 3
  • 32
  • 37
Zheileman
  • 2,509
  • 20
  • 23
  • 1
    You've got a closure in your loop: http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example – ajm May 25 '12 at 13:58

1 Answers1

1

Use the prototype solution, but assign the functions in a loop by passing the current "level" to a function factory.

for (var L in LEVELS)
    MyLogger.prototype[L] = loggerMaker(L)

function loggerMaker(l) {
    return function(message) {
        this.getLogger(l).output(message)
    };
}

Here I used a function to create a new variable scope that references the current L in the loop.

If you're coding only for modern JavaScript environments, I'd use an Array instead of an Object to hold the levels, and then use forEach with an anonymous function.

;['debug','info','warn'].forEach(function(L) {
    MyLogger.prototype[L] = function(message) {
        this.getLogger(L).output(message);
    };
});