2

I am working on a Logging system, and am looking forward to implement a log once method.

What I'm stuck with, is, how would I retrieve unique identifier and/or objects signature, to be used as a hash key?

My idea is:

var Log = {
    messages : {},
    once : function(message)
    {
        // get unique id and/or passed objects signature, use it as a key
        var key = unique( message );

        if ( !Log.messages.hasOwnProperty(key) )
        {
            Log.messages[key] = message;
        }
    }
};

I tried .toString(), but it did return simply [object Object] for a basic object, and [object <type>] for anything else. No ids, no nothing.

I also tried the toSource() function, but in Chrome it did not want to work with basic objects.

What I need, though, is for this to work with every type of object. Be it string, be it integer, be it function, I need to get that signature / id.

Maybe there is an implemention of such function somewhere around already?

Update

This is meant to do logging in a loop, but instead of logging on each iteration, log only once in order to prevent console pollution.

My particular loop is actually a game loop, and I am looking to debug some info.

Like:

for (var i = 0; i < 100; i++)
{
    console.log('message');
}
// this would log 100 entries

Where:

for (var i = 0; i < 100; i++)
{
    Log.once('message');
}
// would execute behind the scenes console.log() only once.
Community
  • 1
  • 1
tomsseisums
  • 13,168
  • 19
  • 83
  • 145
  • 1
    Are just trying to prevent the execution of a function more than once or am I misreading? Or are you trying to prevent a certain `message` from being logged more than once? In which case `message` could be anything from a string to an object? Or would it only be a string? – Ian Dec 18 '12 at 21:47
  • You could push numbers and strings to an array, but that wouldn't work out with objects/functions as `{} !== {}` and `(function foo(){}) !== (function foo(){})`. – Fabrício Matté Dec 18 '12 at 21:56
  • possible duplicate of [unique object identifier in javascript](http://stackoverflow.com/questions/1997661/unique-object-identifier-in-javascript) – Decent Dabbler Dec 18 '12 at 21:59
  • @Ian, yes, I am trying to prevent a certain `message` from being logged more than once. @Fabricio, that's why I am asking for a way to determine unique ID and/or signature. – tomsseisums Dec 18 '12 at 22:00
  • 1
    I think you will want to look at [JavaScript Object Id][1]. [1]: http://stackoverflow.com/questions/2020670/javascript-object-id – Mark Leighton Fisher Dec 18 '12 at 22:02
  • 1
    In a loop that `uniqueId` thingy doesn't help, because everytime I'd call `Log.once()`, it'd create a `new String` instance, hence, incrementing the `id`, and logging again. – tomsseisums Dec 18 '12 at 22:05

1 Answers1

3

You can use JSON.stringify to get a "signature" of arbitrary values. Of course this does not save object types, and does not work for Date or Function instances; also it does not distinguish between different objects with the same values. If you want that, you will need to store a explicit reference to them (of course hindering the garbage collector from freeing them):

var loggedVals = [];
console.once = function() {
    var args = [].slice.call(arguments).filter(function(arg) {
        return (loggedVals.lastIndexOf(arg)==-1) && loggedVals.push(arg);
    });
    if (args.length)
        console.log.apply(console, args);
});

If you don't want to store references to them, you will need to tag them as "logged" by adding a hidden property (just like a UID generator would do it):

… function(arg) {
        return !arg.__hasbeenlogged__ && 
          Object.defineProperty(arg, "__hasbeenlogged__", {value: true});
          // configurable, enumarable and writable are implicitly false
    } …

Notice that this solution does not work for primitive values and even fails for null and undefined - you might need to mix the two approaches.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375