Why doesn't JavaScript function aliasing work? Why doesn't JavaScript function aliasing work? google-chrome google-chrome

Why doesn't JavaScript function aliasing work?


Yes, you should persist the context :

var log;if (window.console && typeof console.log === "function"){  // use apply to preserve context and invocations with multiple arguments  log = function () { console.log.apply(console, arguments); };} else {  log = function(){ return; }}

What is happening is that the context (the this value), is implicitly set when you call a function, for example:

var obj = {  method: function () { return this; }};obj.method() === obj; // true

In this case, you are calling a function that is defined as a property of an object, when the function is invoked, the this value is set to that object.

Now as in your example, if you copy a reference of that method to a variable:

var method = obj.method;method() === window; // global object

As you can see, the this value refers to the global object.

So, to avoid this implicit behavior you can set the context explicitly, with the call or apply functions.


The problem with wrapping a function (like console.log) in a function is that it loses its context, i.e. it will not show the correct line number of the file that we've put our "log" shortcut in.

Instead I suggest something like this:

 window.log = ((window.console && window.console.log) ?              console.log.bind(console) :               function(){});

This works with firebug & chrome dev tools and does not throw errors when no console is available. And - most importantly - shows the correct file & line number.


This doesn't work:

log("hi");

While this does:

log.call(console, "hi");

It is obvious that you need to call the aliased function with the correct context -- as you yourself have mentioned.

I think you'll have to use a function wrapper (a closure that has a reference to the original context) rather than an alias...

Update

Also note that if you check for console directly, you may get a run-time error when the variable doesn't exist. You're better off checking it explicitly as window.console. Here's one way to implement a conditional log wrapper:

var log = (function (console) {    return console        ? function () { console.log.apply(console, arguments); }        : function () {}})(window.console);