---
title: Bound methods in Javascript
date: "2008-11-12T12:00:00Z"
lastmod: "2011-12-02T22:11:39Z"
categories:
- coding
wp_id: 24
description: I solve JavaScript's 'this' binding issues in callbacks by defining methods inside the constructor with closures. I've found this pattern more reliable than prototypes, especially when passing methods to functions like setTimeout or handling closures in loops.
keywords: [javascript, closures, this keyword, prototypes, settimeout, design patterns]
---
The [popular](https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Class-Based_vs._Prototype-Based_Languages) [way](http://javascript.crockford.com/prototypal.html) to create a class in Javascript is to define a function and add methods to its prototype. For example, let's create a class `Node` that has a method `hide().`
```javascript
var Node = function(id) {
this.element = document.getElementById(id);
};
Node.prototype.hide = function() {
this.style.display = "none";
};
```
If you had a header, say
, then this piece of code will hide the element.
```javascript
var node = new Node("header");
node.hide();
```
If I wanted to hide the element a second later, I am tempted to use:
```javascript
var node = new Node("header");
setTimeout(node.hide, 1000);
```
... except that it won't work. `setTimeout` has no idea that the function `node.hide` has anything to do with the object `node`. It just runs the function. When `node.hide()` is called by setTimeout, the `this` object isn't set to `node`, it's set to `window`. `node.hide()` ends up trying to hide `window`, not `node`.
The standard way around this is:
```javascript
var node = new Node("header");
setTimeout(function() {
node.hide();
}, 1000);
```
I've been using this for a while, but it gets tiring. It's so easy to forget to do this. Worse, it [doesn't work very well inside a loop](https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Working_with_Closures#Creating_closures_in_loops.3a_A_common_mistake):
```javascript
for (var id in ["a", "b", "c"]) {
var node = new Node(id);
setTimeout(function() {
node.hide();
}, 1000);
}
```
This actually hides node "c" thrice, and doesn't touch nodes "a" and "b". You've got to remember to wrap every function that contains a function in a loop.
```javascript
for (var id in ["a", "b", "c"]) {
(function() {
var node = new Node(id);
setTimeout(function() {
node.hide();
}, 1000);
})();
}
```
Now, compare that with this:
```javascript
for (var id in ["a", "b", "c"]) {
setTimeout((new Node(id)).hide, 1000);
}
```
Wouldn't something this compact be nice?
To do this, the method `node.hide` must be bound to the object node. That is, `node.hide` must know that it belongs to `node`. And when we call `another_node.hide`, it must know that it belongs to `another_node`. This, incidentally, is the way most other languages behave. For example, on [python](http://www.python.org/), try the following:
```python
>>> class Node:
... def hide():
... pass
...
>>> node = Node()
>>> node
<__main__.Node instance at 0x00BA32D8>
>>> node.hide
>
```
The method `hide` is bound to the object node.
To do this in Javascript, instead of adding the methods to the prototype, you need to do two things:
1. Add the methods to the object in the constructor
2. Don't use `this`. Set another variable called `that` to `this`, and use `that` instead.
```javascript
var Node = function(id) {
var that = this;
that.element = document.getElementById(id);
that.hide = function() {
that.element.style.display = "none";
};
};
```
Now node.hide is bound to node. The following code will work.
```javascript
var node = new Node("header");
setTimeout(node.hide, 1000);
```
I've taken to using this pattern almost exclusively these days, rather than prototype-based methods. It saves a lot of trouble, and I find it makes the code a lot compacter and easier to read.
---
## Comments
- **Hari K T** _3 Jan 2009 6:52 am_:
Good article . .. . .\
Great work . I am trying to implement it tooo....
- **Mani** _2 Dec 2011 8:25 pm_:
A small correction though
var Node = function(id) {
var that = this;
that.element = document.getElementById(id);
that.hide = function() {
that.element.style.display = "none";
}
};
- **[S Anand](http://www.s-anand.net/)** _2 Dec 2011 10:12 pm_:
Thanks Mani -- I've updated the code to reflect your correction.