Getting Out of Binding Situations in JavaScript

by Christophe Porteneuve

54 Reader Comments

Back to the Article
  1. Binding is never required but could save certain issues for sure.
    Copy & paste the code below to embed this comment.
  2. This was a very informative article - I was previously unaware of apply and call in javascript, and had been using lexical closures to preserve binding where I needed it - and in some cases, this was quite clunky. Thanks for the info!
    Copy & paste the code below to embed this comment.
  3. The excellent YUI library does this as well, both in event binding, and for instance YAHOO.lang.later (too preserve scope in window.setTimeout/Interval).
    Copy & paste the code below to embed this comment.

  4. name = ‘Ray’; // Or explictly: window.name = ‘Ray’;
    var john = {
      name: ‘John’,
      greet: function(person) {
      with(this)
        alert(“Hi ” + person + “, my name is ” + name);
      }
    }; john.greet(“Mark”);
    // => “Hi Mark, my name is John”
    Copy & paste the code below to embed this comment.
  5. I’m the “var that = this” kind of person (actually, var scope = this). Scope, and object oriented programming in Javascript in general, has cost me many headaches. This articles gives extra insight and explains binding in a very clear way. Thank you Christophe!
    Copy & paste the code below to embed this comment.
  6. Thank you, it’s very helpful to have related programming tricks brought together like this. In JavaScript you need them to do practically anything more advanced with objects, yet you won’t find it in any language reference — because it’s a usage pattern, not part of the syntax… I’m pretty new to JavaScript, and I have stumbled upon this problem several times already. Solved it with “var that=this” following Douglas Crowford, but creating a helper function might have been much more convenient in many cases. Thank you.
    Copy & paste the code below to embed this comment.
  7. One of the best technical articles I’ve read in a year.  The clarity, level of detail, and the flow from low level to high level is just brilliant. Thank you.  I wish all technical material was in this tone and level.
    Copy & paste the code below to embed this comment.
  8. I have read every alistapart article, and I absolutely love this site, but I still have to say, I’m so sick of everyone from the train-yard bagging PHP. I feel so much animosity from RoR as if there was a war between two of the most promising open source programming solutions. Every time an article is written about OOP PHP is bagged. PHP is much (5 times) faster than Ruby, which is one reason why development of PHP, and new users are growing at such an alarming rate.
    Copy & paste the code below to embed this comment.
  9. Huh, dude? How the hell did you manage to draw that conclusion from an article focusing on Javascript?
    Copy & paste the code below to embed this comment.
  10. Einar> Yes, YUI does it too, sorry I failed to mention it. D’oh, Christian will kill me next time I see him! Andrea> Essentially, @with@ is *evil*. Seriously.  Just about every serious expert will advise against @with@, regardless of the programming language (e.g. JavaScript or Delphi).  Essentially, it tampers too much with scope and binding rules, but also leads to misunderstanding the code in languages with implicit binding (it’s all too easy to skip over the @with@ call while reading the code inside).  Also, in the context of binding, @with@ won’t help much: passing a method reference will lose its binding anyhow.  Consider the following: bq. name = ‘Christophe’;
    var andrea = {
      name: ‘Andrea’,
      introduce: function() { alert(“Hi I’m ” + this.name + ‘!’); }
    };
    function times(count, fx) {
      for (var index = 0; index < count; ++index)
        fx();
    };
    with (andrea)
      times(1, introduce); This will still alert “Hi, I’m Christophe!”.  So you @with@ only introduces confusion”¦ Blaise, Radomir> Thanks, guys! :-) Mina> You just made my day :-) Mike> Er, I can understand your frustration (we Railsers do tend to bash on PHP more than is necessary, or even fair), but where the heck did I even mention Rails in my article?  PHP’s great for specific purposes (e.g. very quickly whipping and deploying a simple online feature), but yes, its OOP support is lackluster, I’m sorry, it’s just true.  Although the situation _vastly_ improved with 5.x, it still doesn’t come close to any other prominent OO language, be it Java, C#, C++, Objective C”¦  Also, I personally believe your speed argument is flawed: speed is not why new people flock to PHP all the time: they do because its learning curve is next to flat, and it’s supported by every single web host out there. Anyway, thanks so much for the feedback everyone!
    Copy & paste the code below to embed this comment.
  11. Alright, so ALA’s comment preview doesn’t live up to actual posting when it comes to code/blockquotes. I wish they’d allow <pre> blocks”¦ Sorry about the mangled code, fellows.  “Grab the cleaned version at Pastie”:http://pastie.org/226352 will you?
    Copy & paste the code below to embed this comment.
  12. The explanation of using append=true in the section on ExtJS and createDelegate is not partial application, not in the way the article uses the term everywhere else at least (the difference is parenthetically explained but not particularly clearly to my mind). Getting partial application with ExtJS seems to require (judging solely by the content of the article as I’ve not used it myself) using 0 as the insertion position. I’m assuming that the section on apply was intended to be indicating that wrapping functions can be made generic since apply takes an array and as such the wrapping function doesn’t need to know what the actual argument list for the wrapped function is, but that is not at all clear to me.  It seems to me that that section, as written, could be read to indicate that apply doesn’t care what order the arguments are in the array and that the function will Just Work, a conclusion that is not at all correct. This may want some clarification in the article.
    Copy & paste the code below to embed this comment.
  13. Etan> indeed, @append@ is not partial application in exactly the same sense I used earlier (pre-filling early arguments), but I think we’re in a slightly superfluous debate about whether pre-filling _last_ arguments is, or isn’t, partial application :-)  Also, I indeed mention that using zero position would result in more commonplace prepending. Glad you paid attention :-) As for the clarification request on @apply@, I’ll be on the lookout for further requests to that effect, but I don’t feel, for now, that it is necessary.  The phrasing so far seems alright to me.
    Copy & paste the code below to embed this comment.
  14. I hate being “that mootools” guy that always pops up in the comments, but I do wish you woulda thrown in a bit about how mootools bind and closure functions[1] work.  It’s bind() and bindWithEvent() functions are extremely useful for binding objects.
    [1]http://docs.mootools.net/Native/Function
    Copy & paste the code below to embed this comment.
  15. Edit, missed that the comment board uses textile.  I do wish you would of thrown in a bit about how mootools “bind and closure functions”:http://docs.mootools.net/Native/Function work.
    Copy & paste the code below to embed this comment.
  16. TJL> Yes, I forwent MooTools, sorry if that irked you.  The lib does provide a number of extensions to the @Function@ prototype, and although I find them a bit haphazard and with quite some overlap, they certainly do the job!  Thanks for posting the focused link.
    Copy & paste the code below to embed this comment.
  17. Good article.  Having had to explain js binding on more than one occasion, it’s nice to have a good explanation written down that I can just link to. One point that I think would have been beneficial to spell out more explicitly is that ‘this’ is resolved at execution time and will refer to
    1) the object provided as first param to call/apply when invoked that way,
    2) the object from which the “method was referenced”:http://pastie.org/226696 (luke.fn = john.greet; luke.fn(“Joe”); // this === luke)
    3) From a “with block”:http://pastie.org/226686 , but please PLEASE don’t do it
    4) the global object (window in browsers) when not invoked from an object. And a special note: ‘this’ can refer to more than just objects:
    var greet = function (a) { return ‘Hi ’ + a; };
    greet.from = function (a,b) { alert(this(a) + “, I’m ” + b); }; greet.from(‘Christophe’,‘John’); // this resolves to the function greet (I’m not suggesting this is good practice, just functional—no pun intended)
    Copy & paste the code below to embed this comment.
  18. Yeah, the comment preview isn’t quite wysiwyg.  Hope that was readable enough.
    Copy & paste the code below to embed this comment.
  19. Luke> Your breakdown of @this@ resolution is nice, although as I explained in an earlier reply, @with@ is not immune to binding loss.  Also, if we walk the line, functions in JS are”¦ objects.  So yes, @this@ references objects :-)
    Copy & paste the code below to embed this comment.
  20. bq. Also, if we walk the line, functions in JS are”¦ objects. So yes, this references objects :-) Touche :-) Of course you understood what I meant (typeof !== ‘object’ vs instanceof Object). While we’re being pedantic, it may also be worth noting (or maybe not) that primitives are converted to their respective String/Number/Boolean object types if passed as the context in call/apply.  Passing null/undefined will cause this === global object (window).  So yes, this will always refer to an instanceof Object.  At least to the best of my knowledge. function fn() { alert(this instanceof String); } fn.call(“string literal, not instanceof String”); // alerts ‘true’ Of course, that sort of code is best avoided (to say the least).
    Copy & paste the code below to embed this comment.
  21. Great article—I’ve been wondering for a while when ALA(A List Apart) 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.
  22. 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.
  23. 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.
  24. 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.
  25. 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.
  26. 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.
  27. 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.
  28. 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.
  29. 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.
  30. 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.
  31. 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()
    # Should give you a box with “Hi! My name is Christophe!” var fx = Christophe.hi
    fx()
    # Haven’t actually tested this. Will it fail, too?
    Copy & paste the code below to embed this comment.
  32. Should be a line break before the fx().
    Copy & paste the code below to embed this comment.
  33. 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.
  34. 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.
  35. 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.
  36. Hey Brian, Well, this solution works _in your particular situation_, and has the regular issues it faces in every other language: # It duplicates the variable name everywhere, making the method code not reusable.
    # 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.
  37. 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.
  38. 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.
  39. 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.
  40. looks like my comment formatting got borked :)
    Copy & paste the code below to embed this comment.
  41. looks like my comment formatting got borked :)
    Copy & paste the code below to embed this comment.
  42. 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.
  43. 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.
  44. 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.
  45. 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.
  46. 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.
  47. 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.
  48. 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.
  49. Sorry trying again to get the formatting correct this time (keeping my fingers crossed! ;) ) name = 'Ray';

    var john = {
     &nbsp;  &nbsp; name: 'John',
     &nbsp;  &nbsp; greet: function(person) {
      &nbsp;  &nbsp; &nbsp;  &nbsp; alert("Hi " + person + ", my name is " + this.name);
     &nbsp;  &nbsp; }
    };

    var doe = {
     &nbsp;  &nbsp; name: 'Doe',
     &nbsp;  &nbsp; fx: john.greet
    };

    doe.fx("Mark"); 
    Copy & paste the code below to embed this comment.
  50. 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.
  51. 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.
  52. 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.
  53. 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.
  54. 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.