I was just reading this question and wanted to try the alias method rather than the function-wrapper method, but I couldn't seem to get it to work in either Firefox 3 or 3.5beta4, or Google Chrome, both in their debug windows and in a test web page.
Firebug:
>>> window.myAlias = document.getElementById
function()
>>> myAlias('item1')
>>> window.myAlias('item1')
>>> document.getElementById('item1')
<div id="item1">
If I put it in a web page, the call to myAlias gives me this error:
uncaught exception: [Exception... "Illegal operation on WrappedNative prototype object" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" location: "JS frame :: file:///[...snip...]/test.html :: <TOP_LEVEL> :: line 7" data: no]
Chrome (with >>>'s inserted for clarity):
>>> window.myAlias = document.getElementById
function getElementById() { [native code] }
>>> window.myAlias('item1')
TypeError: Illegal invocation
>>> document.getElementById('item1')
<div id=?"item1">?
And in the test page, I get the same "Illegal invocation".
Am I doing something wrong? Can anyone else reproduce this?
Also, oddly enough, I just tried and it works in IE8.
In addition to other great answers, there's simple jQuery method $.proxy.
You can alias like this:
Or
You actually can't "pure alias" a function on a predefined object. Therefore, the closest to aliasing you can get without wrapping is by staying within the same object:
Another short answer, just for wrapping/aliasing
console.log
and similar logging methods. They all expect to be in theconsole
context.This is usable when wrapping
console.log
with some fallbacks, in case you or your users have run into trouble when using a browser that doesn't (always) support it. This is not a full solution to that problem though, as it needs to be expanded checks and a fallback - your mileage may vary.Example using warnings
Then use it as usual
If you prefer to see your logging arguments wrapped in an array (I do, most of the time), substitute
.apply(...)
with.call(...)
.Should work with
console.log()
,console.debug()
,console.info()
,console.warn()
,console.error()
. See alsoconsole
on MDN.console firebug
This is a short answer.
The following makes a copy of (a reference to) the function. The problem is that now the function is on the
window
object when it was designed to live on thedocument
object.The alternatives are
or you can use two aliases.
I dug deep to understand this particular behavior and I think I have found a good explanation.
Before I get in to why you are not able to alias
document.getElementById
, I will try to explain how JavaScript functions/objects work.Whenever you invoke a JavaScript function, the JavaScript interpreter determines a scope and passes it to the function.
Consider following function:
This function is declared in the Window scope and when you invoke it the value of
this
inside the sum function will be the globalWindow
object.For the 'sum' function, it doesn't matter what the value of 'this' is as it is not using it.
Consider following function:
When you call dave.getAge function, the JavaScript interpreter sees that you are calling getAge function on the
dave
object, so it setsthis
todave
and calls thegetAge
function.getAge()
will correctly return100
.You may know that in JavaScript you can specify the scope using the
apply
method. Let's try that.In the above line, instead of letting JavaScript decide the scope, you are passing the scope manually as the
bob
object.getAge
will now return200
even though you 'thought' you calledgetAge
on thedave
object.What's the point of all of the above? Functions are 'loosely' attached to your JavaScript objects. E.g. you can do
Let's take the next step.
ageMethod
execution throws an error! What happened?If you read my above points carefully, you would note that
dave.getAge
method was called withdave
asthis
object whereas JavaScript could not determine the 'scope' forageMethod
execution. So it passed global 'Window' as 'this'. Now aswindow
doesn't have abirthDate
property,ageMethod
execution will fail.How to fix this? Simple,
Did all of the above make sense? If it does, then you will be able to explain why you are not able to alias
document.getElementById
:$
is called withwindow
asthis
and ifgetElementById
implementation is expectingthis
to bedocument
, it will fail.Again to fix this, you can do
So why does it work in Internet Explorer?
I don't know the internal implementation of
getElementById
in IE, but a comment in jQuery source (inArray
method implementation) says that in IE,window == document
. If that's the case, then aliasingdocument.getElementById
should work in IE.To illustrate this further, I have created an elaborate example. Have a look at the
Person
function below.For the
Person
function above, here's how the variousgetAge
methods will behave.Let's create two objects using
Person
function.Straight forward, getAge method gets
yogi
object asthis
and outputs100
.JavaScript interepreter sets
window
object asthis
and ourgetAge
method will return-1
.If we set the correct scope, you can use
ageAlias
method.If we pass in some other person object, it will still calculate age correctly.
The
ageSmarter
function captured the originalthis
object so now you don't have to worry about supplying correct scope.The problem with
ageSmarter
is that you can never set the scope to some other object.The
ageSmartest
function will use the original scope if an invalid scope is supplied.You will still be able to pass another
Person
object togetAgeSmartest
. :)You have to bind that method to the document object. Look:
When you’re doing a simple alias, the function is called on the global object, not on the document object. Use a technique called closures to fix this:
This way you don’t loose the reference to the original object.
In 2012, there is the new
bind
method from ES5 that allows us to do this in a fancier way: