Shortening console.log() to l()

2013-02-27 22:10

When doing some quick debugging on frontend code or learning javascript you often have to type a lot of console.log() statements. This becomes pretty annoying, even with code completion. So just for kicks I went after the low hanging fruit and though about shortening it to simply l(). We are all lazy, right?

This turned out be an interesting learning experience.

My first attempt was simply:

function l(){
        console.log.apply(this, arguments);
}

This works beautifully... but only in Firefox/Opera. Chrome complained:

Uncaught TypeError: Illegal invocation

Turns out that console.log is not part of any standard and it is treated as an extension to DOM. That means it's a 'host object' and does not necessarily inherits from Object object.

So depending on implementation it might support the apply() method or not, as we have seen above.

Not giving up, my next idea was to use eval(), and just construct the function arguments/body. But I soon realized this would go nowhere, since I would have to recognize argument type(s). For example check out this invocation:

console.log('%o: %o (%o)', "i am a string", 77, [1, 2, 3]);

If we took arguments and just run something like join(',') on it, we'd end up with a string:

"i am a string,77,1,2,3"

which would definitely not work, since the first parameter, a string variable, doesn't get not enclosed in quotes. To make matters worse, the arrays would be converted to comma-separated strings of their values, and so on.

The way to go is to use the Function facility of javascript. Functions in javascript are actually Function objects. So we can easily create them on the fly with the new operator:

new Function ([arg1[, arg2[, ... argN]],] functionBody)

Solution:

General idea is to take the number of arguments, produce an array of some strings which will be the new function argument names and create a function body which will call console.log on all those arguments.

The while loop produces something like this:

["arg1", "arg2", "arg3"]

You will surely notice the counting starts at 1, so is not very hackerish. However that does not matter, since it's just names of arguments, they could be anything really.

Then we construct the new function:

new Function( args, 'console.log(' + args.join(',') + ')' ).
        apply( null, arguments );

Let's break this down from inside out. The body of the newly created function will be:

console.log(' + args.join(',') + ')

So in our example:

console.log(arg1,arg2,arg3)

Therefore we run

new Function( ["arg1", "arg2", "arg3"], 'console.log(arg1,arg2,arg3)' )

we immediately apply the arguments passed to l() to this new function, so it's executed with those arguments:

.apply( null, arguments );

and provide null for this, since we don't really need it for anything.

That's it!

Read more posts about: