If JavaScript has first-class functions, why doesn’t calling this function in a variable work?

Solution 1:

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);
}

Solution 2:

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

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

Solution 3:

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);
};