Oct 16, 2009

the bind function

John Resig has page Learning Advanced JavaScript to explain how the following script works.

// The .bind method from Prototype.js 
Function.prototype.bind = function(){ 
  var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift(); 
  return function(){ 
    return fn.apply(object, 
      args.concat(Array.prototype.slice.call(arguments))); 
  }; 
};

His explanation is wonderful. And this piece of code is simple, powerful. But it maybe still hard for anyone to understand without any explanation. So I refactored it as follow, and add one use case.

Function.prototype.bind = function() {
    var function_to_be_bound = this;
    //convert argements into a real array
    var args = Array.prototype.slice.call(arguments); 
    //the first element in the array is the context_object to be bound to
    var context_object = args.shift();
    //the rest of elements in the array is the prefilled parameter
    var binding_parameters = args;

    return function() {
        var invoking_parameters = Array.prototype.slice.call(arguments);
        var combined_parameters = binding_parameters.concat(invoking_parameters);
        var result_from_function_run_in_new_context = function_to_be_bound.apply(context_object, combined_parameters);
        return result_from_function_run_in_new_context;
    };
}

function reply_greeting(your_name) {
    //"this" is the context object
    alert("my name is " + this.name + ", Nice to meet you, " + your_name);
}

var fred = { name: "fred" };

var reply_greeting_of_fred_to_you = reply_greeting.bind(fred); 
var reply_greeting_of_fred_to_john = reply_greeting.bind(fred, "john");

reply_greeting_of_fred_to_you("jeff"); //expect: "my name is fred, Nice to meet you, jeff"
reply_greeting_of_fred_to_john(); //expect: "my name is fred, Nice to meet you, john"

Another article may help you to understand is Functional Javascript