22

JavaScript is purported to have first-class functions, so this seems like the following ought to work:

var f = document.getElementById;
var x = f('x');

But it fails on all browsers, with a different cryptic error message on each one. Safari says “Type error”. Chrome says “Illegal invocation”. Firefox says “Could not convert JavaScript argument”.

Why?

3 Answers 3

38

When you call obj.method() in Javascript the method is passed obj as this. Calling document.getElementById('x') with therefore set this to document.

However if you just write f = document.getElementById you now have a new reference to the function, but that reference is no longer "bound" to document.

So your code doesn't work because when you call f as a bare function name it ends up bound to the global object (window). As soon as the innards of the function try to use this it finds that it now has a window instead of a document and unsurprisingly it doesn't like it.

You can make f work if you call it so:

var x = f.call(document, 'x');

which calls f but explicitly sets the context to document.

The others way to fix this is to use Function.bind() which is available in ES5 and above:

var f = document.getElementById.bind(document);

and is really just a generalised short cut for creating your own wrapper that correctly sets the context:

function f(id) {
    return document.getElementById(id);
}
Sign up to request clarification or add additional context in comments.

Comments

24

Because in JavaScript functions arent bound to context (this). You may use bind():

var f = document.getElementById.bind(document);

1 Comment

To clarify this answer, this in document.getElementById() is document, while this where you're executing your scope is the global scope, aka this is the window object.
4

Using ES6's spread operator, you could also try:

function f(){
    return document.getElementById(...arguments);
};

Babel gives this:

function f() {
    var _document;
    return (_document = document).getElementById.apply(_document, arguments);
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.