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.
Copy & paste the code below to embed this comment.
Einar Qvale
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.
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 OOPPHP 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.
Christophe Porteneuve
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:
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.
Copy & paste the code below to embed this comment.
Etan Reisner
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.
Christophe Porteneuve
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.
T.J. L
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 functions1 work. It’s bind() and bindWithEvent() functions are extremely useful for binding objects.
Copy & paste the code below to embed this comment.
Christophe Porteneuve
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)
Copy & paste the code below to embed this comment.
Christophe Porteneuve
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 :-)
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.
Jordan Gray
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.
Ryan Cooke
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;
}
Copy & paste the code below to embed this comment.
Christophe Porteneuve
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.
Ryan Cooke
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.
Christophe Porteneuve
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.
Copy & paste the code below to embed this comment.
Christophe Porteneuve
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!”
Copy & paste the code below to embed this comment.
Christophe Porteneuve
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’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.
Christophe Porteneuve
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.
Copy & paste the code below to embed this comment.
Christophe Porteneuve
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 :) )
Copy & paste the code below to embed this comment.
Christophe Porteneuve
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!
Copy & paste the code below to embed this comment.
Erico Lendzian
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.
Christophe Porteneuve
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.
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.
varun grover
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);
}
};
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.
Christophe Porteneuve
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.
Copy & paste the code below to embed this comment.
coco
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?…..
54 Reader Comments
Back to the Articlea gatt
Binding is never required but could save certain issues for sure.
Jeremiah Dodds
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!
Einar Qvale
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).
Andrea Giammarchi
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”
Blaise Kal
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!
Radomir Dopieralski
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.
Mina Naguib
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.
Mike Mike
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.
Srdjan Pejic
Huh, dude? How the hell did you manage to draw that conclusion from an article focusing on Javascript?
Christophe Porteneuve
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,
withis evil. Seriously. Just about every serious expert will advise againstwith, 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 thewithcall while reading the code inside). Also, in the context of binding,withwon’t help much: passing a method reference will lose its binding anyhow. Consider the following:This will still alert “Hi, I’m Christophe!”. So you
withonly 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!
Christophe Porteneuve
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?
Etan Reisner
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.
Christophe Porteneuve
Etan> indeed,
appendis 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.T.J. L
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 functions1 work. It’s bind() and bindWithEvent() functions are extremely useful for binding objects.
T.J. L
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.
Christophe Porteneuve
TJL> Yes, I forwent MooTools, sorry if that irked you. The lib does provide a number of extensions to the
Functionprototype, and although I find them a bit haphazard and with quite some overlap, they certainly do the job! Thanks for posting the focused link.Luke Smith
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)
Luke Smith
Yeah, the comment preview isn’t quite wysiwyg. Hope that was readable enough.
Christophe Porteneuve
Luke> Your breakdown of
thisresolution is nice, although as I explained in an earlier reply,withis not immune to binding loss. Also, if we walk the line, functions in JS are”¦ objects. So yes,thisreferences objects :-)Luke Smith
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).
Jordan Gray
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
bindfunction, 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.Ryan Cooke
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.
Ryan Cooke
Also thwarted by the preview, here’s the formatted code at Pastie:
http://pastie.org/227266
Christophe Porteneuve
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
elodieobject’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”¦Ryan Cooke
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 :-}?
Amadeus Demarzi
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)
Christophe Porteneuve
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 :-)
Eddie Welker
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.
Christophe Porteneuve
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
myPersonfunction 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.prototypewith abindmechanism does).The two approaches address a rather different set of requirements and constraints, basically.
I hope this helps your thoughts on the subject”¦ :-)
James Bennett
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).
Brian Warshaw
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()
var fx = Christophe.hi
fx()
Brian Warshaw
Should be a line break before the fx().
Christophe Porteneuve
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
selfargument 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.
Brian Warshaw
I see where mine would fail after looking at the article again—instantiation (makes sense, duh).
Brian Warshaw
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”?
Christophe Porteneuve
Hey Brian,
Well, this solution works in your particular situation, and has the regular issues it faces in every other language:
Basically you use a situation where you don’t need
this”¦ But the whole binding discussion is about situations when we do needthis, because we have multiple instances using our method and need to reference the current instance, but don’t wantthisto wander astray.Er, was that clear?
Christophe Porteneuve
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
Enumerablein Prototype, for instance), and the like.Brian Warshaw
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).
Amadeus Demarzi
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 :) )
Amadeus Demarzi
looks like my comment formatting got borked :)
Amadeus Demarzi
looks like my comment formatting got borked :)
Christophe Porteneuve
Amadeus: alright, but what you’re playing with here is just a local function, so it actually wouldn’t even need the
instanceparameter if you’re calling it directly:thisstill 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 accessquickCheck, 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”¦
Matt Hackett
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!
the undertaker fdhg
as #8 mentioned, i love ala but i have to say that i stop reading any article when it begins with php is bad….
Erico Lendzian
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?
Christophe Porteneuve
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
Dmitry Gorbunov
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
varun grover
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”);
varun grover
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”);
Richard Davies
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!
Christophe Porteneuve
Hey Varun,
Well, doh!
Look at your code:
doe.fx(‘Mark’)This code explicitly calls method
fxon objectdoe. This is explicit binding, as described at the beginning of the article. As thefxmethod 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.
Christophe Porteneuve
Richard: why, thank you. ‘most welcome, such “a-ha!” moments are the specific goal of writing such a piece :-)
Mike Mike
I apologize for insulting your post. I don’t know how I got on these comments.
coco
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