Getting Out of Binding Situations in JavaScript

by Christophe Porteneuve

54 Reader Comments

Back to the Article
  1. Great article—I’ve been wondering for a while when ALA would get onto this! Besides, I always prefer the articles about code to the more philosophical essays.

    Since you mentioned Prototype’s bind function, it’s only fair to give honourable mention to Daniel Brockman, upon whose code it seems to be modelled. He wrote “an excellent article(Object-Oriented Event Listening through Partial Application in JavaScript)”:http://www.brockman.se/writing/method-references.html.utf8 about the binding problem, with particular reference to event listeners, back in 2004. I’ve been employing his solution to good effect for the past couple of years.

    Copy & paste the code below to embed this comment.
  2. Good article that illuminates JavaScript’s more powerful OO functionality. Personally I like how binding abstracts execution from data, allowing a coder to write objects that are like a cross between an abstract class and an interface. Implementations are not differentiated by distinct code but by the data they operate on, aka context. Here’s using your example:

    function Person(first, last, age) {
      this.first = first;
      this.last = last;
      this.age = age;
    }

    Person.prototype = {
      _getFullName: function() {
        alert(this.first + ’ ’ + this.last);
      },
      _greet: function(other) {
        alert(“Hi ” + other.first + “, I’m ” + »
        this.first + “.”);
      }
    };

    var elodie = {
      proto: new Person(‘Elodie’, ‘Jaubert’, 27),
      getFullName: function() { elodie._getFullName.call(elodie); },
      greet: function(other) { elodie._greet.call(elodie, other); }
    };

    For the memory-leak conscious, this implementation is also closure-free.

    Copy & paste the code below to embed this comment.
  3. Also thwarted by the preview, here’s the formatted code at Pastie:

    http://pastie.org/227266

    Copy & paste the code below to embed this comment.
  4. Ryan> Your point on binding letting us split context and behavior is well taken (and very true), but woah!  Why on Earth would you declare the elodie object’s __proto__ (already a pretty obscure property to most JS developers) to be a new Elodie object?  That’s just weird!  The example is fairly convoluted for no proper reason, I’m afraid :-/  I don’t mean to be rude, but I believe it fails to illuminate good practices”¦

    Copy & paste the code below to embed this comment.
  5. Here’s my reason: closures are hard to conceptualize and, because of their implicit declaration, often completely missed. To a strict and unaware programmer, closures can make broken-looking code seem to “magically” work. And with an extremely popular browser that can’t handle closures properly, my good practices are to avoid them altogether. The goal is to write code that can be used anywhere over and over without detriment, ie programming to interfaces.

    Therefore explicitly assigning the prototype chain to a parent class reinforces the idea of prototyping as inheritance as opposed to the more common use of simple declaration.

    As far as alternative practices, you correctly pointed out that “[extra] method calls are costly”. And really, you are saying “var that = this;” isn’t convoluted at all :-}?

    Copy & paste the code below to embed this comment.
  6. I often find it simpler to build into the function arguments an instance variable, and then on call, pass this.

    function cool(instance)
    {
    alert(instance.reason);
    }

    Then I just execute cool(this).

    Would there be good reason NOT to do this? (outside the debate of closures)

    Copy & paste the code below to embed this comment.
  7. Amadeus: this practice is essentially “not doing OOP.”  You’re just creating a bunch of functions, possibly (read: preferably) in a namespace, and calling them without context; the “instance” is just the first argument.

    It certainly works, and actually is how OOP is processed under the hood, obviously.  But it requires that all your signatures, down to the tiniest call level that needs the context, are equipped with a context argument.  When programming in the large, this approach is getting a bit hard to maintain/guarantee.

    Then, obviously, there’s the issue of code aesthetics, which is personal to each of us.  I, for one, dislike the looks of this style, but that’s just me :-)

    Copy & paste the code below to embed this comment.
  8. Hi Christophe, great article.  It prompted a lot of discussion with co-workers.

    I have a question (or two).  I’m not a javascript expert, but I read (skim) a lot of articles that usually tell me enough to get by.  When I read your section on recognizing patterns, I wrote up a solution which avoids the problems using a closure.  (I won’t try to paste it, it’s here: “http://pastie.org/228035”:http://pastie.org/228035 ).

    So I know you’re using prototypal inheritance, and I’m not sure what I’m using… but I do know…  your method, while being easier to understand, still has to deal with the binding problems, and allows direct access to it’s properties.  While mine solves both.  I also know that you probably know a lot more than I do.

    So, (finally) getting to my questions, is there a reason why you choose to use prototypal instead of a method using closures? Are there performance issues or something that I am unaware of?  I’m curious, because while I have seen things comparing method with the other, I haven’t really come across anything which tells me why one method is better than another, or one should be used rather than the other.  I’m interested in your thoughts.

    Copy & paste the code below to embed this comment.
  9. Hey Eddie, thanks for sharing.

    OK, so your method is essentially about emulating private members thanks to a closure pattern, as discussed by Douglas Crockford a long time ago.

    It seems to me, upon cursory inspection, that your wrapping it in an extra direct-call layer as per the module pattern is a bit superfluous: I don’t see how “just creating the myPerson function the regular way”:http://pastie.org/228312 would shed any privacy your class enjoys”¦

    The main difference between your solution and a regular prototypal inheritance-based approach is: yours is closed.  It is good for situations where you don’t want any code to monkeypatch your class, ever (which may very well be valid in specific situations you encounter).  It also does not provide a generic means of “binding” a method you did not write (which equipping Function.prototype with a bind mechanism does).

    The two approaches address a rather different set of requirements and constraints, basically.

    I hope this helps your thoughts on the subject”¦ :-)

    Copy & paste the code below to embed this comment.
  10. Christophe, writing a function to accept the object instance as an argument most certainly can be object-oriented; one need only look at Python for an example (it’s hard to argue Python isn’t an OO language, seeing as everything in Python is an object and the “under the hood” way the language works is based entirely around invoking methods of objects).

    Your argument that this hurts “programming in the large”, then, would seem to be contradicted by reality, because there are plenty of large applications and systems of applications written in Python. This leaves the subjective argument which, really, seems to be the only argument there is against this style; I personally don’t have any problems with the fact that Python requires ‘self’ to be declared as an argument, and it certainly has some advantages (in terms of regularity and simplification of the language and working with the language).

    Copy & paste the code below to embed this comment.
  11. Sorry if I missed this in someone else’s comment, and I’m sure I’m wrong, because this must have been thought of already, but what about binding with a syntax similar to the static binding in Java, Ruby, and even PHP?

    So why not:

    var Christophe = {
    name: ‘Christophe’,
    hi:function() {
    alert(“Hi! My name is” + Christophe.name + “!”);
    }
    }

    Christophe.hi()

    1. Should give you a box with “Hi! My name is Christophe!”

    var fx = Christophe.hi
    fx()

    1. Haven’t actually tested this. Will it fail, too?

    Copy & paste the code below to embed this comment.
  12. Should be a line break before the fx().

    Copy & paste the code below to embed this comment.
  13. James: I agree that Python seems like a good counter-argument; thanks for bringing that up.  Python’s a pretty cool thing, but I would argue that the self argument there is a mandatory constraint: it’s just the way the language works, it’s the official way to declare methods (or isn’t it?).

    On the other hand, JavaScript calls methods the regular way, so going this-as-argument basically goes against the flow, and may be counter-intuitive to users of your API.

    I will, quite certainly, concede that there is a large amount of subjectivity in the choice, though; and to my own personal sense of code aesthetics, this-as-argument in a language such as JS reeks too much of OOP-emulation in non-OOP languages, hence part of my reluctance.

    Copy & paste the code below to embed this comment.
  14. I see where mine would fail after looking at the article again—instantiation (makes sense, duh).

    Copy & paste the code below to embed this comment.
  15. I’ve been playing with it some more, and my question is this: how often do you find yourself needing to pass a method reference instead of a reference to an object that will ultimately perform the method? I’m sure you have plenty of examples and that’s why you wrote this, but I’m mainly curious to hear about some of them. When would you need such an abstract “method launcher”?

    Copy & paste the code below to embed this comment.
  16. Hey Brian,

    Well, this solution works in your particular situation, and has the regular issues it faces in every other language:

    1. It duplicates the variable name everywhere, making the method code not reusable.
    2. It only works for a singleton object: you’re defining a singleton here, not a class to be instantiated.  As soon as you want multiples instances like this, the named reference won’t cut it.

    Basically you use a situation where you don’t need this”¦ But the whole binding discussion is about situations when we do need this, because we have multiple instances using our method and need to reference the current instance, but don’t want this to wander astray.

    Er, was that clear?

    Copy & paste the code below to embed this comment.
  17. Bryan, there are tons of examples.  The most common one is using methods as event handlers that still need to access their instance’s properties and methods in their code.

    Any kind of publish/subscribe system, such as custom events or decoupled UI system, would also apply.

    Basically, anywhere you would find “method pointers”, so: generic algorithms, iterators (any call to methods from Enumerable in Prototype, for instance), and the like.

    Copy & paste the code below to embed this comment.
  18. Thanks for the replies, Christophe. Makes perfect sense now, though makes me feel like I wish web tech didn’t move at the speed of molasses. If only all browsers supported a JavaScript based on some of the more recent ECMA specs (even Actionscript is a better implementation at this point).

    Copy & paste the code below to embed this comment.
  19. I actually over simplified my example, here’s an example:

    var MyGame = function(){…};

    myGame.prototype.Interact = function()
    {
    var quickCheck = function(instance){…A quick function only used by Interact with instance, only required in Interact…}
    /* …do some stuff… */

    quickCheck(this);
    }

    The idea would be a I create these mini functions within my prototype objects to perform various tasks that would be repeated multiple times throughout Interact.

    (Bear with me a bit here as I feel I can get quite a bit done in javascript but some of my definitions/verbage may be a bit noob :) )

    Copy & paste the code below to embed this comment.
  20. looks like my comment formatting got borked :)

    Copy & paste the code below to embed this comment.
  21. looks like my comment formatting got borked :)

    Copy & paste the code below to embed this comment.
  22. Amadeus: alright, but what you’re playing with here is just a local function, so it actually wouldn’t even need the instance parameter if you’re calling it directly: this still resolves to the surrounding instance.  If you’re passing it to iterators and the like, then fine.  At any rate, your method’s code is the only one that can access quickCheck, so you have full control over its usage and binding resolution.

    But this schema doesn’t work with publicly-accessible methods, as these can get used by external code over which you have no control, meaning they may well pass references around without binding”¦

    Copy & paste the code below to embed this comment.
  23. Nice article! I particularly appreciate that you covered all the basics, and even mentioned when certain patterns weren’t necessary. Hopefully this will help alleviate some of the ignorance about the language out there. Thanks!

    Copy & paste the code below to embed this comment.
  24. as #8 mentioned, i love ala but i have to say that i stop reading any article when it begins with php is bad….

    Copy & paste the code below to embed this comment.
  25. I found this article incredible helpful. I’m saving it for later, can’t remember how many times I’ve had this problems while OOPing with Javascript.
    I resorted to use prototype binding functions, but i find (my) solutions rather un-elegant.
    Christophe, what book would you recommend to learn OOP in Javascript?

    Copy & paste the code below to embed this comment.
  26. Hey Erico,

    I’m not too sure.  Since you mention it, obviously Prototype’s class system is alright when it comes to OOP in JavaScript, although it doesn’t facilitate stuff like true private methods.  So in this regard “my book”:http://thebungeebook.net and “Andrew Dupont’s”:http://apress.com/book/view/1590599195 are pretty good resources.

    On general JavaScript, John Resig’s “Pro JavaScript Techniques”:http://apress.com/book/view/1590597273 has an excellent part II, about 60 pages, that covers JavaScript-based OOP and code reuse.

    HTH

    Copy & paste the code below to embed this comment.
  27. Hello, Christophe!
    Thanks for this great article. I have translated it into Russian. I hope you don’t mind :) The link is http://habrahabr.ru/blog/javascript/46773.html

    Copy & paste the code below to embed this comment.
  28. Hi Christophe,

    Really nicely written, thanks a ton! Just another (interesting?) fact that I noticed is that if we pass the method reference (method belongs to say obj1) to another object’s member (say this object is obj2), the “this” keyword inside the passed method would now refer to the second object obj2. here is the snippet (i think the formatting will get lost, but anyways)


    name = ‘Ray’; // Or explictly: window.name = ‘Ray’;
    var john = {
      name: ‘John’,
      greet: function(person) {
        alert(“Hi ”  person  ”, my name is ” + this.name);
      }
    };

    var doe = {
      name: ‘Doe’,
      fx: john.greet
    };

    doe.fx(“Mark”); 

    Copy & paste the code below to embed this comment.
  29. Sorry trying again to get the formatting correct this time (keeping my fingers crossed! ;) )


    name = ‘Ray’;

    var john = {
          name: ‘John’,
          greet: function(person) {
                alert(“Hi ”  person  ”, my name is ” + this.name);
          }
    };

    var doe = {
          name: ‘Doe’,
          fx: john.greet
    };

    doe.fx(“Mark”); 

    Copy & paste the code below to embed this comment.
  30. Awesome article. JavaScript binding is something that I’ve only partially understood… just enough to know to try adding a Prototype bind() to any function calls that don’t work and see if that fixes it.

    After reading this article, it all makes sense finally! Thank you!

    Copy & paste the code below to embed this comment.
  31. Hey Varun,

    Well, doh!

    Look at your code:

    doe.fx(‘Mark’)

    This code explicitly calls method fx on object doe.  This is explicit binding, as described at the beginning of the article.  As the fx method was not pre-bound, it uses the explicit binding you give it.

    As I said, methods are not intrinsically attached to a given object.  They use whatever binding is applicable when they’re run.

    ‘hope this makes it clearer for you.

    Copy & paste the code below to embed this comment.
  32. Richard: why, thank you.  ‘most welcome, such “a-ha!” moments are the specific goal of writing such a piece :-)

    Copy & paste the code below to embed this comment.
  33. I apologize for insulting your post. I don’t know how I got on these comments.

    Copy & paste the code below to embed this comment.
  34. thanks for this article…I’ve readed many articles about this (even book’s capitules) and never it had been clear to me…your articles was better than all that books…

    now I’ve a question..why js do it in this way?…I think many times than seemed be a complications in a language in a future this became in advantages…like closures or metaprogramming in ruby…but this binding look very weird to me…this has any advantage?…..

    thank you again and good luck

    Copy & paste the code below to embed this comment.