Early and Late Binding

  1. Use cases/mistakes
  2. Binding with var self = this
  3. Early binding
    1. Function.prototype.bind
    2. Comparison
  4. Late binding
    1. Problems of early binding
    2. The late binding in action
  5. Summary

JavaScript sets value of the execution context "this" at call time. Being a bless of flexibility, this is also a curse of wrong context.

There are numerous situations when a function must keep the context no matter how it runs, and reference same object.

Use cases/mistakes

As a working example, we take a Menu constructor, which should accept an element and create a menu on it’s base.

Something like this:

function Menu(elem) {
  // ...
}

// Usage:
var elem = document.getElementById('something') // a DOM element
var menu = new Menu(elem)

Most often use cases (and sources of mistakes) are:

setTimeout
When you setup setTimeout, you may want it to reference the object:

function Menu(elem) {

  setTimeout(function() {
*!*
    alert(this)  // window, not menu!
*/!*
  }, 1000)

}

new Menu(document.createElement('div'))

But this references window, because setTimeout always executes the function in window context.

So, there is no way to call Menu methods in the code above.

onclick
function Menu(elem) {

  elem.onclick = function() {
*!*
    alert(this)  // elem, not menu!
*/!*
  }
}

An element event handler always sets this to elem instead of menu.

Again, the reference to the object is lost.

Private method / local function
A local function is often used as a private method.
function Menu(elem) {

  function privateMethod() {
*!*
    alert(this)  // window, not menu!
*/!*
  }

  // ... call private method
  privateMethod()
}

new Menu(document.createElement('div'))

A simple call to privateMethod() uses this = window.

Naturally, we need ways to mitigate the problem, so that our function can access the menu object. And fortunately, there is more than one.

Binding with var self = this

First, we can store a reference to this in the closure.

In the example below, this is copied to a new variable self. This variable is then used instead of this.

function Menu(elem) {

  *!*var self = this*/!*

  setTimeout(function() {
*!*
    alert(self)  // object! (menu)
*/!*
  }, 1000)

}

new Menu(document.createElement('div'))

Works equally with event handlers, local functions etc. All we need is a closure to put var self = this.

Early binding

We could use a helper function bind which forces this.

Below is an example of such function. It accepts a function func and returns a wrapper which calls func with this = fixThis.

function bind(func, fixThis) {  
  return function() {
    return func.apply(fixThis, arguments)
  }
}

This time let’s take an event handler.

function Menu(elem) {

  elem.onclick = bind(function() {
    alert(this)  // object! (menu)
  }, this)

}

How to access the element?

If this is bound permanently to the handler, then it replaces the reference to the element. So, the element becomes inaccessible, right?

Of course not. In the example above, elem can be retrieved from the closure.

elem.onclick = bind(function() {
  alert(elem)  // element ;)
}, this)

..But that may not work in other cases. For example, in the loop:

// ...
for(var i=0; i<10; i++) {
  elem = ...
  elem.onclick = bind(function() {
    alert(this)  
  }, this)
}

The first option in this case is to fix the code to keep elem. See the task Shooters in the loop for details.

The second option is when you are using a JavaScript framework to assign event handlers. Then the event object comes to the resque with it’s currentTarget property.

var handler = bind(function(e) {
  alert(e.currentTarget)  
}, this)

// using jQuery here. Any other framework will do.
$(elem).click(handler)

The role of the framework here is to provide e.currentTarget in IE<9. It is not supported by default, but all modern frameworks “fix” the event object, so the approach works.

Function.prototype.bind

There is a native Function.prototype.bind method which does exactly the same, plus it allows to fix arguments.

It is supported by most modern browsers. For those which don’t support, we can emulate it:

Function.prototype.bind = Function.prototype.bind || function(fixThis) {
  var func = this  
  return function() {
    return func.apply(fixThis, arguments)
  }
}

Polluting native prototypes is generally not recommended, but modifying Function.prototype is somewhat acceptable. It doesn’t affect iteration over objects and arrays, so side-effects are minimal.

The emulation above is not as powerful as a native implementation, because it doesn’t allow to provide arguments. See the Prototype framework for a full version. Anyway, it does what we need here.

The binding becomes even simpler now.

setTimeout
When you setup setTimeout, you may want it to reference the object:

function Menu(elem) {

  setTimeout(function() {
    alert(this)  // object! (menu)
  }*!*.bind(this)*/!*, 1000)

}

new Menu(document.createElement('div'))

onclick
function Menu(elem) {

  elem.onclick = function() {
    alert(this)  // object! (menu)
  }*!*.bind(this)*/!*

}

Private method / local function
That’s a bit trickier, because you can’t call a method in FunctionDeclaration:

function Menu(elem) {

  function privateMethod() {
    alert(this) 
  }.bind(this) // syntax error, can't call method in-place

}

So need to use FunctionExpression:

function Menu(elem) {

  var privateMethod = function() {
    alert(this) 
  }*!*.bind(this)*/!*

  // ... now all fine, "this" is fixed
  privateMethod()
}

new Menu(document.createElement('div'))

Comparison

Let’s compare bind versus var self = this approach. Green is where bind wins:

  • bind does not depend on closure. The binding occurs instantly and lasts forever. Can be used without closures at all.
  • You have to add bind for every function which needs the context. That’s longer and sometimes less elegant than a single var self = this.
  • There is no additional variable "self". Saves time on refactoring.

In fact, both ways find their use. Which one you use more often is up to your personal style.

Late binding

Late binding is a variation of bind with slightly different behavior.

In short, it means “binding on call time”, instead of “immediate binding”.

Problems of early binding

For example, here’s a code of a novice, who knows nothing about late binding. The code is buggy.

It outputs “Menu” on click, but it should output “SuperMenu”. Try to find out why by the means of a piercing programmer’s look.

<!DOCTYLE HTML>
<html>
<body>

<script>
function bind(func, fixThis) { // using custom bind for simplicity
  return function() {
    return func.apply(fixThis, arguments)
  }
}

function Menu(elem) {

  this.sayHi = function() { alert('Menu') }

  elem.onclick = bind(this.sayHi, this)
}

function SuperMenu(elem) { 
  Menu.apply(this, arguments)
  
  this.sayHi = function() { alert('SuperMenu') }
}

new SuperMenu(document.body)
</script>

Click me. I'm a SuperMenu!

</body>
</html>
Open the code in new window

The code uses “All-in-one constructor” pattern to inherit SuperMenu from Menu. It is described in All-in-one constructor pattern.

Did you try? I hope, you found the reason successfully.

Of course, the problem occurs, because onclick uses this.sayHi of Menu, not that of SuperMenu.

The late binding in action

To use late binding, we use bindLate instead of bind:

<!DOCTYLE HTML>
<html>
<body>

<script>
function bindLate(funcName, fixThis) { // instead of bind
  return function() {
    return fixThis[funcName].apply(fixThis, arguments)
  }
}

function Menu(elem) {

  this.sayHi = function() { alert('Menu') }

  elem.onclick = bindLate('sayHi', this)
}

function SuperMenu(elem) { 
  Menu.apply(this, arguments)
  
  this.sayHi = function() { alert('SuperMenu') }
}

new SuperMenu(document.body)
</script>

Click me. I'm a SuperMenu! (now working)

</body>
</html>
Open the code in new window

Now it works. The change is:

elem.onclick = bindLate('sayHi', this)

The wrapper created by bindLate resolves the object method at calling time, so the bug is fixed.

Of course, bindLate works for object methods only.

There are frameworks which have late binding built in. For example, in jQuery there is a function $.proxy which can do both early and late binding depending on how it is called.

Summary

There are 3 binding methods:

  1. Save this in a local variable (var self = this) and use it inside nested functions.
  2. Bind a function to proper this with bind - especially convenient when it’s in Function.prototype.
  3. Use late binding for a method call if the method may change or doesn’t exist at the time of binding.

All methods have their pros and contras. Together they are indeed useful. Happy binding Smile

Tutorial

Donate

Donate to this project