Most developers don’t know about—or don’t care enough about—binding in JavaScript. Yet this single issue is responsible for a sizeable portion of the questions on most JavaScript-related support channels, and thousands—if not millions—of hairs being tortured away from developer heads every single day. Yet with a little attention to this oft-overlooked subject, you can avoid wasting your time, energy, and patience and move on to more powerful, efficient scripting.
Why should we care about binding?#section2
Almost no major object-oriented programming (OOP) languages force you to consider binding. That is, they don’t require you to explicitly qualify access to the current object’s members (methods and properties) with a reference such as this
or self
. If you’re calling a method on no particular object, you’re usually calling it on the current object. The same goes when you’re passing a method around for later invocation: it will retain its current object. In short, for most OOP languages, binding is implicit. This is true in Java, C#, Ruby, Delphi, and C++, to name but a few.
PHP and JavaScript do require you to explicitly state which object you’re accessing, even if it’s the current one. (And that is about as far as I’m willing to put PHP and JavaScript in the same basket.)
Of course, neither PHP nor JavaScript are actually object-oriented in the traditional sense. In the case of PHP, object support was added, rather slapdash, as an afterthought; even in PHP5, functions are not first-order values, and many OOP features are lackluster. JavaScript is very dynamic and relies on “prototypal inheritance,” which is a significantly different paradigm than class-based inheritance. Such distinctions do not immediately relate to binding issues, but demonstrate that traditional object-related syntaxes and behaviors were of little importance to the designers of JavaScript.
In JavaScript, binding is always explicit, and can easily be lost, so a method using this
will not refer to the proper object in all situations, unless you force it to. Overall, binding in JavaScript is not a difficult concept, but it is far too often ignored or glossed over by JavaScripters, which leads to confusion.
Let’s step in it#section3
Consider the following, innocuous-looking examples, and how their actual behavior can seem unpredictable.
var john = { name: 'John', greet: function(person) { alert("Hi " + person + ", my name is " + name); } };john.greet("Mark"); // => "Hi Mark, my name is "
Okay, that’s weird. Where did the name go? Well, we were guilty of a binding assumption here: our method just refers to name
, which JavaScript will look for in the several valid levels of variables, ending up with the properties of the window
object. Of course our window does have a name
property, but it’s empty by default, so no name shows up.
Let’s try it out:
name = 'Ray'; // Or explictly: window.name = 'Ray'; var john = { name: 'John', greet: function(person) { alert("Hi " + person + ", my name is " + name); } };john.greet("Mark"); // => "Hi Mark, my name is Ray"
Well, that’s just dandy, but useless. What we want is our object’s name
property, not the one in window
! Here is where explicit binding is important:
var john = { name: 'John', greet: function(person) { alert("Hi " + person + ", my name is " + this.name); } };john.greet("Mark"); // => "Hi Mark, my name is John"
Notice how we prefix our reference to name
with the keyword this
: that’s explicit binding. And indeed it works! Or does it? (Line wraps marked » —Ed.)
var john = { name: 'John', greet: function(person) { alert("Hi " + person + ", my name is " + this.name); } };var fx = john.greet; fx("Mark"); // => "Hi Mark, my name is " (or "Hi Mark, my name » is Ray" depending on where you're trying it)
Perhaps you’re not familiar with languages that treat functions as first-order values, in which case the line var fx = john.greet;
may seem weird. This does not call the greet
method, but creates a reference to it—an alias of sorts, if you will. Hence, calling fx
ends up calling the greet
method. However, we’re apparently in some trouble all of a sudden: we’re explicitly using the this
keyword, yet it does not use John. What gives?
This is the single most important issue with JavaScript binding—something I’ll refer to as “binding loss.” It happens whenever you’re accessing a method through a reference instead of directly through its owner object. The method loses its implicit binding, and this
stops referencing its owner object and goes back to its default value, which in this case is window
(so if window
had a name
property by then, it would be used).
Recognizing binding-sensitive code patterns#section4
Binding-sensitive code patterns involve passing method references, which usually happens through two possible means: either you’re assigning a method as a value, or you’re passing a method as an argument (which is essentially the same thing, when you think about it).
Consider the following simple class definition (Line wraps marked » —Ed.):
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 + "."); } };
Let’s try it out (Line wraps marked » —Ed.):
var elodie = new Person('Elodie', 'Jaubert', 27); var christophe = new Person('Christophe', » 'Porteneuve', 30); christophe.greet(elodie); // => "Hi Elodie, I'm Christophe."
Looking good so far. Let’s push ahead:
function times(n, fx, arg) { for (var index = 0; index < n; ++index) { fx(arg); } }times(3, christophe.greet, elodie); // => Three times "Hi Elodie, I'm undefined." times(1, elodie.getFullName); // => "undefined undefined"
Whoa—we’re in trouble! What’s with the undefined? We lost our binding when we passed greet
and getFullName
as arguments, so their this
reference points to the window
object, which does not have the first
and last
properties. Boom.
When you do all your JavaScript heavy lifting by hand, as we just did, you’re usually more aware of such issues. But when you rely on a framework to handle the basics, binding can elude you, leaving you writing simple code that just borks. Consider the following Prototype-based snippet:
this.items.each(function(item) { // Process item this.markItemAsProcessed(item); });
This code will trigger an error stating that the markItemAsProcessed
method is undefined. Why is that? Because you just passed each
a reference to an anonymous function, so this
in there refers to window
, not to what it was outside each
. This is a very common mistake, and makes up a fair share of the questions on the framework mailing lists.
Binding explicitly#section5
So how do we fix it? We bind explicitly—that is, we explicitly state to what this
will point to within the method when it gets called. And how do we do that? JavaScript provides us with two options: apply
and call
.
Apply within#section6
Every JavaScript function is equipped with an apply
method that allows you to call that function with specific binding (a specific this
, if you will). It takes two arguments: the binding object, and an array of the arguments to be passed to the function. Here’s an example based on our previous code:
var fx = christophe.greet; fx.apply(christophe, [elodie]); // => "Hi Elodie, I'm Christophe."
The nice thing with an array is, you don’t need to know in advance which arguments the function you’ll call apply
on will take. You can write code independent of the actual argument list—just construct the array any way you want, and pass it on. You can also take an existing array of arguments and tweak it to your heart’s content before passing it along.
Call now#section7
When you do know exactly which arguments you want to pass, call
may feel nicer, as it takes the arguments themselves, not an array of them:
var fx = christophe.greet; fx.call(christophe, elodie); // => "Hi Elodie, I'm Christophe."
However, with call
you lose the flexibility of an array. It all depends on your particular situation: aside from this difference, apply
and call
have identical semantics and behavior.
Note, by the way, that the method does not actually need to belong to the object you’re binding it to: as long as it uses this
in ways that are compatible with its binding (read: with members that exist in its bound object), we’re in the clear. Such flexibility is possible because JavaScript is a dynamic language that resolves member access at runtime—when the access happens—a feature sometimes referred to as “late binding.” You’ll also find late binding in just about every scripting language (e.g., Perl, Ruby, Python, PHP) and, incidentally, OLE Automation.
Losing the shackles#section8
It’s nice to have a way to specify binding, but the problem is, you can only specify it at invocation time. You can’t, say, specify it in advance and then let some other code invoke your properly bound method when it sees fit. This is a major problem, because when we pass method references around, we’re doing just that: letting other code choose when to invoke methods.
So what we want is a way to persistently bind a method, so that we get a bound method reference, so to speak. The only way to achieve this requires us to wrap our original method in another one, that will perform the apply
call. Here’s a stab at it:
function createBoundedWrapper(object, method) { return function() { return method.apply(object, arguments); }; }
If you’re not too keen on JavaScript, the code above may confuse you a bit. The idea here is that calling createBoundedWrapper
with a given object and method (which, presumably, belongs to said object) will produce a brand new function (the anonymous one we’re returning).
That function, when called, will take our original method and invoke apply
on it, passing:
- the original object’s binding (the variable named
object
), and - whatever arguments were provided at call time, as an array.
(Every function has an automatic arguments
variable that behaves as an array of all the arguments that were passed to it.)
Let’s try it out (Line wraps marked » —Ed.):
var chrisGreet = createBoundedWrapper(christophe, » christophe.greet); chrisGreet(elodie); // "Hi Elodie, I'm Christophe."
Ah-ha! It works! We created a bound method reference based on christophe
and its greet
method.
JavaScript frameworks do it#section9
Our createBoundedWrapper
function is neat, but may prove a bit unwieldy. If you’re smart about your JavaScript work, you’ll probably rely on a framework to smooth out browser incompatibilities, ease DOM access, and enhance JavaScript. So let’s have a look at how a few popular JavaScript frameworks deal with method binding.
Prototype#section10
Prototype has long equipped functions with a bind
method that lets you do just that:
var chrisGreet = christophe.greet.bind(christophe); chrisGreet(elodie);
Far too few people know that bind
also allows you to do “partial application”—that is, pre-filling one or more arguments. For instance, let’s say you have a method that toggles the active status of a feature:
var coolBehavior = { // ... toggle: function(enabled) { this.enabled = enabled; // ... }, // ... };
You can easily define two shortcuts—enable
and disable
—in the following way (Line wraps marked » —Ed.):
coolBehavior.enable = coolBehavior.toggle.bind » (coolBehavior, true); coolBehavior.disable = coolBehavior.toggle.bind » (coolBehavior, false);// And then: coolBehavior.enable();
A note on proper usage: sometimes, bind
was used for pre-filling only, without interest in the binding. Something like the following may be seen in code:
function times (count, fx) { for (var index = 0; index < count; ++index) { fx(); } } // ... var threeTimes = times.bind(null, 3); // ... threeTimes(someFunction);
So as a side note, with Prototype 1.6, if you’re only interested in pre-filling, prefer curry
—it preserves the current binding and focuses on argument pre-filling:
var threeTimes = times.curry(3);
Ext JS#section11
The Ext JS library tailors binding through a method added to functions, called createDelegate
. The syntax goes like this (Line wraps marked » —Ed.):
method.createDelegate(scope[, argArray] » [, appendArgs = false])
First, note that the extra arguments you may specify are provided as an array, instead of inline: myMethod.createDelegate(scope, [arg1, arg2])
, not myMethod.createDelegate(scope, arg1, arg2)
.
Another important nuance is that these arguments will replace whatever arguments you pass at call time, instead of resulting in partial application. If you want the latter, you need to pass true
(which will append the argument array, when Prototype would prepend them instead) or an insert position as a third argument (typically, using zero will prepend). Here’s an example lifted from the API documentation (Line wraps marked » —Ed.):
var fn = scope.func1.createDelegate(scope, » [arg1, arg2], true); fn(a, b, c); // => scope.func1(a, b, c, arg1, arg2);var fn = scope.func1.createDelegate(scope, » [arg1, arg2]); fn(a, b, c); // => scope.func1(arg1, arg2);var fn = scope.func1.createDelegate(scope, » [arg1, arg2], 1); fn(a, b, c); // => scope.func1(a, arg1, arg2, b, c);
Dojo#section12
The Dojo toolkit also caters to method binding with the humorously named hitch
function. The syntax is:
dojo.hitch(scope, methodOrMethodName[, arg…])
Interestingly, the method can be passed either directly, or using its name. Extra arguments, if any, are passed before actual, call-time arguments. Here are a few examples:
var fn = dojo.hitch(scope, func1) fn(a, b, c); // => scope.func1(a, b, c);var fn = dojo.hitch(scope, func1, arg1, arg2) fn(a, b, c); // => scope.func1(arg1, arg2, a, b, c);
Base2#section13
Dean Edwards’ superb Base2 library acts as a least common denominator of sorts to all JavaScript libraries by ironing out all the annoying differences in JavaScript implementations. It acknowledges a binding facility is needed and provides a simple bind
function:
base2.bind(method, scope[, arg]);
Note the scope object comes second, not first. Aside from that, the semantics are strictly equivalent to Prototype’s bind
or Dojo’s hitch
:
var fn = base2.bind(func1, scope) fn(a, b, c); // => scope.func1(a, b, c);var fn = base2.bind(func1, scope, arg1, arg2) fn(a, b, c); // => scope.func1(arg1, arg2, a, b, c);
jQuery#section14
jQuery does not provide such a binding facility. The library’s philosophy favors closures over binding and forces users to jump through hoops (that is, manually combine lexical closures and apply
or call
, much as other libraries do internally) when they actually need to pass along a piece of code referring to “instance members.”
Should you even bind?#section15
Now that we’ve been through the details of binding, it’s only fair to stress that sometimes, binding is overkill. Specifically, there’s a code pattern in which binding can be replaced, with significant performance profit, by using the lexical closure. (If you’re not clear on a what a closure is, don’t panic.)
Here’s the pattern: some code within a method relies on an anonymous function passed by reference to work. That anonymous function needs to access the surrounding method’s this
keyword. For instance, assuming for a minute we have the each
iterator within arrays, consider the following code again:
// ... processItems: function() { this.items.each(function(item) { // Process item… this.markItemAsProcessed(item); }); }, // ...
The issue here is that the anonymous function holding the actual processing code is passed as an argument to each
, and therefore loses the current binding. When it attempts to call this.markItemAsProcessed
, it crashes because window
has no such method.
Many developers are quick to fix that with binding. Using Prototype, for instance, they would add the following tweak:
// ... processItems: function() { this.items.each(function(item) { // Process item this.markItemAsProcessed(item); }.bind(this)); }, // ...
Notice the trailing call to bind
. However, such code is not as good an idea as it may seem. We saw that achieving such a “bound reference” requires us to wrap the original method within an anonymous function, which means calling the bound method reference results in two method calls: our anonymous wrapper, and the original method. And if there’s one thing true of just about any language, it’s that method calls are costly.
In this situation, we have access to the original, desired this
keyword in the same code location where we define and call the faulty function (the anonymous method we’re passing as an argument to each
). We can simply save the proper this
reference in a local variable, and use that inside our iteration function:
// ... processItems: function() { var that = this; this.items.each(function(item) { // Process item that.markItemAsProcessed(item); }); }, // ...
Look, Ma! No binding! This code uses a language feature called “lexical closure.” In short, closures let code at point A access identifiers declared in scopes surrounding A. Here, our anonymous function has access to variables in the surrounding function—our processItems
method. Such a closure will be maintained by the JavaScript runtime no matter what, so there is no extra cost to using it. Even if there were, I’m fairly confident that it would be far less than the cost of an extra function call at every turn of the loop.
Be cautious about your bindings: sometimes closures provide a simpler, shorter, and better way. (Which is, I believe, precisely why jQuery decided to “force” its users to think about the best option for each situation by having them deal with binding manually.) While closures do have their own set of problems—ill-employed, they can result in memory leaks for certain browsers—the usage I recommend here is pretty safe.
Takeaway points#section16
To recap:
- Any member access must be qualified with the object it pertains to, even when it is
this
. - Any sort of function reference (assigning as a value, passing as an argument) loses the function’s original binding.
- JavaScript provides two equivalent ways of explicitly specifying a function’s binding when calling it:
apply
andcall
. - Creating a “bound method reference” requires an anonymous wrapper function, and a calling cost. In specific situations, leveraging closures may be a better alternative.
And now, with the help of this article, you’ll have no trouble in binding situations!
Binding is never required but could save certain issues for sure.
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!
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).
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"
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!
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.
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.
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.
Huh, dude? How the hell did you manage to draw that conclusion from an article focusing on Javascript?
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!
Alright, so ALA’s comment preview doesn’t live up to actual posting when it comes to code/blockquotes.
I wish they’d allow
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.
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.
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
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.
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.
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)
Yeah, the comment preview isn’t quite wysiwyg. Hope that was readable enough.
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 🙂
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).
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.
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.
Also thwarted by the preview, here’s the formatted code at Pastie:
http://pastie.org/227266
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”¦
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 :-}?
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)
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 🙂
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.
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”¦ 🙂
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).
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?
Should be a line break before the fx().
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.
I see where mine would fail after looking at the article again–instantiation (makes sense, duh).
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”?
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?
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.
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).
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 🙂 )
looks like my comment formatting got borked 🙂
looks like my comment formatting got borked 🙂
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”¦
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!
as #8 mentioned, i love ala but i have to say that i stop reading any article when it begins with php is bad….
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?
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
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
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)
[code]
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”);
[/code]
Sorry trying again to get the formatting correct this time (keeping my fingers crossed! 😉 )
[code]
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”);
[/code]
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!
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.
Richard: why, thank you. ‘most welcome, such “a-ha!” moments are the specific goal of writing such a piece 🙂
I apologize for insulting your post. I don’t know how I got on these comments.
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