0

I'm trying to get under the covers a little bit and get to understanding and not regurgitating code. I'm aware that bind, call and apply change the execution context by modifying what this points to. What I do not understand, is are arenas in which these methods are indispensable and/or lead to much shorter code. Consider the following:

var person = {
            firstName: 'john',
            lastName: 'doe',
            fullName: function () {
                console.log(this.firstName + " " + this.lastName);
            }
        }
//#1, binder is an html button
$('#binder').click(person.fullName.bind(person)); //john doe

//#2, anonymous is an html button
$('#anonymous').click(function () {
    person.fullName(); //john doe
});

//seems strange I see this application a lot 'borrowing' a method
//why?
var o = { firstName: 'obj', lastName: 'ect' };
person.fullName.call(o); //obj ect to console

I would like to know some general paradigms about when it's good practice and/or a huge time saver to use call and apply (and bind outside of the not using anonymous functions a la function #1)

Barmar
  • 741,623
  • 53
  • 500
  • 612
wootscootinboogie
  • 8,461
  • 33
  • 112
  • 197
  • 1
    Another useful aspect of apply is that it lets you pass an array of arguments. Particular useful in situations where a function accepts a variable number of arguments, a la [jquery's `when`](http://stackoverflow.com/questions/4878887/how-do-you-work-with-an-array-of-jquery-deferreds) – James Montagne Jan 14 '14 at 21:21
  • This is basically good for code reusability. – Alex Shilman Jan 14 '14 at 21:22

2 Answers2

2

To focus on where each of these features are indispensable, I would say

  • apply is most useful when dealing with variadic functions. It lets you convert an array of values into an argument list.

    function logwrapper(f){
      return function(){
        console.log("called");
        return f.apply(this, arguments);
      }
    }
    
    var bar = function(){ ... }
    var foo = logwrapper(bar);
    
  • bind is most useful when you want to pass a method into some code that expects just a function. A common example is settimeout and other functions that expect callbacks:

    setTimeout(function(){ obj.meth(); }, 100); //handwritten callback
    
    setTimeout(obj.meth.bind(obj), 100);        //Function.prototype.bind
    
    setTimeout(bind(obj, "meth"), 100);         //Some JS libraries have functions that
                                                //let you write the object only once.
    

    Just keep in mind that IE <=8 does not support the native Function.prototype.bind. You might need to use a polyfill or helper library in that case.

  • call is mostly useful for borrowing methods, as you already noticed. If this is going to be useful or not is going to depend a lot on your particular use case but an important use that is very common is using array methods on the arguments. For historical reasons, arguments doesn't have any of the usual array methods (slice, map, etc) so you need to borrow them:

    function myvariadic(x){
       var rest = [].slice.call(x, 1);
    }
    

    Another example you might see is the hasOwnProerty method:

    for(k in obj){
       if(Object.prototype.hasOwnProperty.call(obj, k)){
          ....
       }
    }
    

    This lets you call the real hasOwnProperty method even if the object shadows it with a hasOwnProperty key of its own.

hugomg
  • 68,213
  • 24
  • 160
  • 246
1

Frankly I don't give a twopenny toss about good or bad practices.
If your aim is to understand anything at all, you'd better forget about them.

This being said, to understand when it is appropriate to use call/apply or bind, what you have to understand is closures, and the specific closure of this.

I use a broad definition of closure here. Not the one you will usually get in JavaScript technical chats, where we usually talk about lexical closures.

For the purpose of this little post, let's say a closure will be anything that provides a value for any variable (this included) that lives outside the current scope of the function you're focusing on.

bind, call and apply are basically there to supply a value for this (and some other arguments as an option).

It is only useful for two things:

  • invoke functions or methods of a given class to an object of a different class (or no class at all).

more on that later

  • supply a value for this in case the current closure does not suit your needs.

For instance, passing a reference to a method loses the connection to the underlying object instance. Or using a class prototype function. Or being called in the context of an event handler where JS has set this to the DOM element that caught the event.

call & apply

call will simply set this to the value of its first argument for this particular execution of the function.

Since creating objects is so easy in JS, you might want to do something like:

Worker = function ()
{
    this.things_done = 0;
}

Worker.prototype = {
    do_something: function (count)
    {
        this.things_done += count;
    }
}

var worker= new Worker();                  // Worker object
var wanabee_worker = { things_done: 100 }; // classless object

Et voilà! You've just created something that has no class relation with Worker but still can use Worker methods, since it has all the required properties defined.

worker.do_something.call (wanabee_worker, 10);

allows wanabee_worker to borrow unrelated object Worker's methods.

The opposite can also be used:

function reset_work_count ()
{
    this.things_done = 0;
}

reset_work_count.call (worker);

Here we have a plain function that does not have anything to do with Worker, except it uses the same properties. call allows to apply it to a Worker object.

apply does exactly the same as far as this is concerned. The only difference is the way other arguments are passed.

bind

bind will create an internal closure and return a new wrapper function that will use the parameter passed to bind as a value for this.

Typical example: bind an event handler to a specific object.

$('#binder').click(person.fullName.bind(person));

Beneath the JQuery goo, what the code does eventually is

binder.addEventListener ('click', person.fullName.bind(person), false);

If the handler was simply defined as person.fullName, it would be called with this set to the DOM element that caught the event.

In that particular case, the closure of this provided by the JS engine does not suit our needs, so we provide an alternative one using bind.

Instead of person.fullName.bind(person), you could have used:

function() { person.FullName(); }

except that

  • the lambda function is cumbersome and obfucates the code,
  • bind is an internal construct that does the closure a bit more efficiently.

You could also imagine that the object used to handle the event will be dynamically allocated/computed by some proxy function. In that case, using bind would be useless since what we want is access to the methods that will allow us to use a lambda object as one of a working class.

function event_handler (param)
{
    var obj = compute_lambda_obj ();
    Worker.prototype.do_something.call (ojb, param);
}
Community
  • 1
  • 1
kuroi neko
  • 8,479
  • 1
  • 19
  • 43
  • 2
    To nit pick a bit, `this` doesnt really have anything to do with closures. Closures are all about lexically scoped variables while `this`, being totally dynamically scoped is kind of the opposite... – hugomg Jan 15 '14 at 01:46
  • If you define closure as the mechanism that resolves external symbols, `this` is a perfect example of something that can only come from a closure. Dynamically or not, it is always scoped outside of a JavaScript function. Call it "current value" if you prefer, as long as it makes people realize there is nothing magic about it :). – kuroi neko Jan 15 '14 at 01:54
  • 2
    `this` is not really a "current value" that gets stored between function calls though. Unlike variables from an outer scope that the inner function might have closed over, `this` behaves more like an extra function parameter that you need to pass every time you call your functions. – hugomg Jan 15 '14 at 01:58
  • ... Or you could see it as a global variable that gets tinkered with by the JS engine, so that you'd better take a copy before your next event handler ruins it. Don't get me wrong: I find JavaScript a very clever language, and most of the times a delight to use for its simplicity and adaptability. I simply don't fall for all the religion that goes with it. All this being said, I totally agree I used my own definition of closure, which could have been misleading, and I modified my post to warn a casual reader about that. – kuroi neko Jan 15 '14 at 02:07
  • 1
    @missingno: From a semantic viewpoint you can call it a closure - it's a function bundled with instance-specific data that is available when executing the code. However, you are right that this is not a *lexical* closure as the `this` value is not a variable from an (outer) lexical scope. – Bergi Jan 15 '14 at 14:40
  • @Bergi Thanks for putting your finger on it. Closure in a general sense is not limited to lexical closure. – kuroi neko Jan 15 '14 at 14:52