Tales from the Evil Empire

Bertrand Le Roy's blog

From closures to prototypes, part 1

There are basically two ways to define classes in BLOCKED SCRIPT closures, where the constructor of the class both adds methods to the new instance and provides a common context for them, and prototypes, which are the first place JavaScript will look at when looking for a member that isn't directly defined on the instance. Don't worry if you don't understand everything I just said, I'll show and explain.

Closures are functions that are defined in a context. This context is the sum of all the objects that are defined at the scope where the function is defined. The catch is that the function not only can access this context, it will also take it with itself everywhere it goes. In other words, closures are functions that remember where they came from. In JavaScript, functions automatically get that quality. Here's an example:

function createClosure(a) {
  var b = 42;
  return function(c) {
    return "a=" + a + ", b=" + b + ", c=" + c;
  }
}

var closure1 = createClosure(1);
alert(closure1(8)); // a=1, b=42, c=8
alert(closure1(9)); // a=1, b=42, c=9

var closure2 = createClosure(2);
alert(closure2(10)); // a=2, b=42, c=10
Coupled with the semantics of the this pointer, closures enable the construction of class instances that have real private variables:
function Point(x, y) {
  var _x = x;
  var _y = y;

  this.get_x() {
    return _x;
  }

  this.get_y() {
    return _y;
  }
}

In this example, we have constructed a truly immutable Point structure. There is no way to modify the private members _x and _y, and you can only get their values through the accessors. It's nice to have truly private members and it's actually useful to build security in mashup scenarios where pieces of code come from untrusted sources. It's extremely tricky to get right but it can be done.

Now in most other situations, it's not really of paramount importance that your private variables remain untouchable. Actually, in .NET, private members are accessible through reflection. You need reflection permissions, but they sure are accessible. Furthermore, there is one circumstance where you do want your private variables very accessible, and that is when debugging. Inspecting private fields is one of the main things you want to be able to do from a debugger, especially when property accessors are not being automatically evaluated by the tool.

So even if it seemed like a good idea to get really private variables, well it really isn't (except when you really, really need them).

But there's another problem with closure-based classes and that's performance. For every instance you create, all the methods have to be recreated. This means that you pay a higher price to object creation and that the working set gets bigger with each instance.

Let's look at prototype-based classes and see the pros and cons of that approach. Here's the same point structure built using prototypes:

function Point(x, y) {
  this._x = x;
  this._y = y;
}
Point.prototype.get_x = function() {
  return this._x;
}
Point.prototype.get_y = function() {
  return this._y;
}

In this case, _x and _y are only private by convention. Nothing prevents anyone from tampering with them. In most cases though, that's fine, and you actually want that to be possible from the debugger.

Performance-wise, prototypes are also better in almost every situation. First, they minimize the working set: here, there's only one copy of the get_x and get_y functions for all Point instances. What differentiates the instances is only what this points to. In terms of speed, creating instances is faster, but calling methods is just a little slower because of the need to lookup the method on the prototype chain.

So far, Atlas has been using closures. Starting with the next version, all of our classes will be using prototypes. Closures are still supported but prototypes are the recommended pattern.

In part 2, I'll show how to easily transition a closure-based Atlas class library to prototypes, with clear do's and don't's.

Read on: http://weblogs.asp.net/bleroy/archive/2006/10/14/From-closures-to-prototypes_2C00_-part-2.aspx

Comments

Manuel Abadia's ASP.NET stuff said:

This posts completes the Microsoft AJAX library OOP enhancements, giving a lot o

# October 11, 2006 7:20 AM

Travis James said:

This is a great article. I suppose in the next installment you will cover how prototypes can be dangerous when expecting "virtual" function behavior and the fact that prototypes are static instances that, once defined, change the behavior of all versions of the function called after a new prototype has been defined? Because the Atlas closure model with the "getTypeDescriptor()" semantic allows for overriding and calling "base class implementations" it might be confusing to make the right decision about what model to use.
# October 11, 2006 8:51 AM

michael said:

what about the following? same thing, just seems easier to read/associate the grouping. function Point(x, y){ this._x = x; this._y = y; } Point.prototype = { get_x: function() { return this._x; }, get_y: function() { return this._y; } } var x = new Point(2,5); alert(x.get_x());
# October 11, 2006 10:05 AM

Wallym said:

Awesome. Thansk Bertrand.
# October 11, 2006 10:20 AM

Bertrand Le Roy said:

Michael: yes, absolutely, this will be covered in part 2, and it is the style we're using in our own classes but I wanted to stay out of any Atlas-isms in the first part. There's something missing in your example though, as if you set the prototype this way, you also need to (re)set the constructor. If using Atlas, this is taken care of when registering the class. More on that later.

# October 11, 2006 12:22 PM

Atlas notes said:

It seems that the next MS AJAX preview will be very, very different from the previous CTP. Bertrand Le

# October 11, 2006 3:45 PM

David Barkol said:

So it's been a while since the last Atlas CTP was released (July). By now, if you've been following...

# October 12, 2006 3:07 AM

Atlas and more said:

In part 1 of this post, I exposed the differences between the closure and the prototype patterns to define

# October 14, 2006 3:22 AM

inventive title said:

Microsoft has been hard at work on the next Microsoft ASP.NET AJAX (formerly "Atlas") CTP,

# October 20, 2006 9:52 AM

Christophe Lauer, Blog Edition said:

Scott Guthrie l'annonce sur son blog via un billet fort détaillé . La version Beta 1 de Microsoft ASP.NET

# October 20, 2006 12:25 PM

Fox Blogs said:

Pour compléter le billet de Patrice il y a la beta 1 de Microsoft ASP.NET Ajax Extentions de dispo mais

# October 20, 2006 7:26 PM

I Love C# said:

Good post on this subject by Bertrand Le Roy

# October 21, 2006 8:14 PM

LudovicoVan said:

Hello, I really do not get the point of this article. I would point out that JavaScript is a great dynamic language, and it is not simply a downgraded version of an OO language. Here is how I would write a real life Point constructor: this.Point = function (x, y) { this.x = x; this.y = y; }; When you need a private member, or a closure, it is because you need it. That is, know your language... My two cents. -LV
# October 29, 2006 10:48 PM

Bertrand Le Roy said:

Ludovico: this is *sample code* that has no other goal than to illustrate the discussion.

If I had to write a point in "real life", I would do var point = {x: x, y: y};

Thank you very much for explaining JavaScript to me but you have to think in the context of a larger and more useful class and transpose what I'm saying to that context.

# October 30, 2006 1:44 PM

LudovicoVan said:

Indeed, that is what I meant: there are no "classes" in JavaScript!!! (And, btw, what you show above does not make more sense, unless you need a singleton point.) Please, don't take this personally, it isn't. IMHO *all* the .Net JavaScript built-in code, be it AJAX, validation, or whatever, is simply broken since its very design. You guys are thinking in terms of object orientation, but JavaScript is completely another beast. It is not a question of the single constructs. It is how you architect a program in JavaScript. It is apparent that you guys are not more than very knowledgeable beginners in this, coming from another field, that is OO... Here is a JavaScript guru: http://www.crockford.com/javascript/ Best regards. -LV
# October 30, 2006 9:35 PM

LudovicoVan said:

> Your position is highly dogmatic and difficult to hold.

The ECMA standard has since the very beginning been tagged to be buggy from the JavaScript gurus. And they not only didn't fix the flows, they are since then trying to add more. On the other hand, I would note that C# 3.0 is making the opposite move. So I am confident in regard to the future. An even bigger mess.

> How do you explain "new", "this", "instanceof" or "constructor"?

Here is a quote from Mr. Crockford:

Is JavaScript object-oriented? It has objects which can contain data and methods that act upon that data. Objects can contain other objects. It does not have classes, but it does have constructors which do what classes do, including acting as containers for class variables and methods. It does not have class-oriented inheritance, but it does have prototype-oriented inheritance.

The two main ways of building up object systems are by inheritance (is-a) and by aggregation (has-a). JavaScript does both, but its dynamic nature allows it to excel at aggregation.

> quite a lot of people still to this day consider that OOP is the best way to build reusable code and applications above a certain size

Yes, as well as we know most of the software projects around keep miserably under-perform.

Please, don't laugh at that...

Cheers. -LV

# October 31, 2006 2:57 AM

Bertrand Le Roy said:

Is that so? How do you explain "new", "this", "instanceof" or "constructor"? What about sections 13.2 and 15 of the EcmaScript specs? How come JavaScript 2.0 has "class" and "namespace"? Are these also misguided attempts from beginners in the field to make JavaScript what it's not?

Your position is highly dogmatic and difficult to hold.

Furthermore, quite a lot of people still to this day consider that OOP is the best way to build reusable code and applications above a certain size. There is a demand today for frameworks that enable the application of reliable engineering methods to the browser. Our users, as well as the users of Dojo or other frameworks don't seem to consider modern JavaScript frameworks to be "broken since [their] very design". At least it seems to solve a real-world problem.

# October 31, 2006 3:03 AM

Bertrand Le Roy said:

Except from citing "JavaScript gurus", what good arguments do you have? Saying that EcmaScript is broken is arrogant at best if you don't elaborate. What about JavaScript 2.0? Is it broken too? So are all these people highly incompetent and only you and Mr. Crockford have understood the True Nature of JavaScript?

How does the Atlas type system prevent you from doing aggregation? I've even published a blog post on the subject a while ago with some sample code, and although I quite like the whole idea, most of the feedback I got was that it was only marginally useful.

I'm really sorry that you don't share our views on client-side development but we're going to continue in this direction anyway as most of the feedback we get encourage us to do so.

# October 31, 2006 3:12 AM

Miljan Braticevic said:

We have recently completed converting our suite of user interface controls from the latest Community

# October 31, 2006 4:45 PM

Bertrand Le Roy said:

LudovicoVan's latest comment was somehow confused for spam, but I salvaged it from my mail notifications so here it is:

"I won't explain what is in the FAQ and any self-claiming JavaScript programmer should know, like we know what Response.Write does in ASP. For those new to JavaScript, and have never heard about <strong>Mr. Crockford</strong>, here are few hints:

These are the contributors to the comp.lang.javascript FAQ: http://www.jibbering.com/faq/faq_notes/contributors.html, and you will see a certain <strong>Mr. Cornford</strong> there.

Now, here is Cornford's introduction to OO techniques in JS: http://www.litotes.demon.co.uk/js_info/private_static.html, and you will see it makes reference to a certain <strong>Mr. Crockford</strong> since the very first paragraph, and builds on his work.

Any decent JavaScript programmer knows who Crockford is and what he did for this language. The rest, I have already said.

Hope this clarifies and helps.

Sincerely. -LudovicoVan"

Dear Ludovico, I know very very well who Mr. Crockford is, thank you very much. Quotes can be used to cite, not only in a sarcastic way. I was not being sarcastic about him being a JavaScript guru, I was merely citing you: "The ECMA standard has since the very beginning been tagged to be buggy from the JavaScript gurus," and encouraging you to be more specific. How is it buggy? Who are "the JavaScript gurus" you talk about? Do you have anything more than authority arguments to substantiate that claim?

And for the third time, what about JavaScript 2.0? Ever heard of Brendan Eich?

I encourage you to read this, which should clear a lot of confusion:

http://developer.mozilla.org/presentations/xtech2006/javascript/

# November 1, 2006 2:09 AM

LudovicoVan said:

Hey man, with all respect, you keep pushing up the "great" work in progress, and we might discuss that in depth, yet my original observation was of a more basic nature: JavaScript is an object-based dynamic language, while you are approaching it as a standard OO language, and building frameworks over this misconception.

I might be wrong, but I can't be clearer than I am.

Best luck to the team, and also to the unfortunate that happens to build on this stuff.

Bye. -LV

# November 1, 2006 4:10 AM

LudovicoVan said:

Now, you know, that is as well feedback from the community. ;) -LV
# November 1, 2006 9:38 AM

Bertrand Le Roy said:

Yes, that is feedback, but you are so far the *only one* to give us that kind of feedback. You seem to be confusing object oriented and class-based. JavaScript is object-oriented, but not class-based in the current version. We recognize and use the prototype and dynamic nature of JavaScript, but at the same time, we agree with experts such as Brendan Eich that there is also a need for classes and we're answering that need while waiting for JavaScript 2 to be available on all browsers. For example, representing widgets and behaviors with class instances is extremely useful and opens up lots of possibilities.

# November 1, 2006 12:01 PM
Leave a Comment

(required) 

(required) 

(optional)

(required)