Javacript: Binding, call and apply methods

Continuing my interest in Javascript this would be second in the series of Posts revisiting the basics of Javascript.

One of the many things that I have been ignorant about when it comes to Javascript is the existence of bindings. Like Ruby ( and other languages) Javascript uses bindings to allow functions to be called with reference to a specific object.

I like to think of this as something similar to instance_eval in Ruby or the binding method.

Instance_eval evaluates an object in the context of an object its called with so lets take a simple example in Ruby


class Cat
def speak
 "miaow"
end
end

class Dog
def speak
"Bark"
end
end

d = Dog.new
=> #
>> c = Cat.new
=> #
>> c.instance_eval{ speak }
=> "miaow"

All this describes is that the speak method is invoked with reference to the instance c (Cat Object)

Similarly the binding method

class Person
  def bind
   @var = "Person Object"
  binding
 end
end

>> p= Person.new
=> #
>> b = p.bind
=> #
>> eval("@var", b)
=> "Person Object"

“binding” which is a kernel method provides us with a binding or snapshot of the context at a particular place in the code where it retains the execution context such as the variable values (@var in this example) which can be used at a later point. With eval we evaluate the value of the @var variable with respect to the binding generated earlier.

Similary Javascript provides us with the apply and call methods. Based on Christophe Porteneuve’s example on the listapart blog here is a simple example to illustrate the use of apply
and call methods


function Song(band, album, song){
	this.band = band;
	this.album = album;
	this.song = song;
	
	this.info = function(other){
		console.log(this);
			alert( 'Did you know '  + other.band + " covered " + this.band + "\'s " + this.song ); 
		}
		
	
	
}



var korn = new Song('Korn','Another Brick in the Wall', 'Another Brick in the Wall' );
var pink = new Song('Pink Floyd', 'The Wall', 'Another Brick in the Wall');

pink.info(korn);

In this case we see a message that says “Did you know Korn covered Pink Floyd’s Another Brick in the Wall”. So thats cool.

The problem occurs when the reference is lost (binding loss: when you assign a method to a variable or pass it as an argument). So lets append this to our earlier example

function display_info(fn, args){
	
		fn(args);
	
}

display_info(pink.info, korn);

Now we see “Did you know Korn covered undefined’s undefined”. The logger statement in the info method will show you that “this” actually is pointing to the window object and not Object of type Song. This is because the minute the binding it lost “this” starts referring to the default binding that is the window object.

So we solve the problem using call or apply. Add this to the bottom of the display_info method

	fn.apply(pink, [korn]);
	fn.call(pink, korn);

Now we see it works again. All we do here with the call and apply method is specify explicitly that we would be invoking the fn i.e. pink.info with reference to the pink object with the korn object as an argument.

So whats the difference between call an apply then? Nothing except that call expects individual arguments to be passed while apply accepts an array

        fn.apply(BindingObject, ArrayArgument);
	fn.call(BindingObject, Argument1, Argument2...);

The inferences drawn in this post have been learned from Christophe Porteneuve’s post titled Getting Out of Binding Situations in JavaScript from the ListApart Blog. Its an awesome post and definitely a must read if your interested in Javascript.