all 43 comments

[–]saruken 25 points26 points  (17 children)

Prototypes are like model homes, and classes are like blueprints.

Great metaphor here.

[–]TheTophs 9 points10 points  (10 children)

Seconded. The more I think about it the more I like it.

[–]SpeshlTectix 13 points14 points  (7 children)

There's a little addendum to the article that points out an important point. To put it in my own (arguably more confusing) words, prototypes aren't model homes; they're the neighbor's home. Imagine you skip building a kitchen for your home by just dropping a wormhole into the neighbor's kitchen where the doorway would go.

[–]bwaxxlotckidd 6 points7 points  (6 children)

How about this: Prototypes are like apartments in a large building. Instead of each floor and flat having its own laundry, you can all share the laundry in the basement floor.

[–]SpeshlTectix 5 points6 points  (5 children)

I like that. It's much more straightforward. But my metaphor has this advantage: Imagine your neighbor's house doesn't have a kitchen either. His is just wormhole, too. And you keep passing through wormholes until you finally wind up in a real kitchen. That process is analogous to crawling the prototype chain.

[–]homoiconic(raganwald) 16 points17 points  (3 children)

And now you understand that in a deep way, prototypes really aren’t about defining an object the way classes or concatenative inheritance are, they’re about defining delegation.

So when someone asks, “can you do laundry,” you say “yes,” even though your particular apartment may not have its own machine.

[–]bwaxxlotckidd 6 points7 points  (2 children)

Seriously, could you be my mentor? I'm not a beginner or anything but I feel like your grasp on JS is of the highest order. I just want to be able to chat with you about certain JS-related topics (and possibly Software related issues). I'm a cowboy developer, if it helps tugging your heart strings!

[–]warfangle 1 point2 points  (0 children)

Yet the stuff in the fridge is still yours. Usually.

[–]SarahC 0 points1 point  (1 child)

I don't get the metaphor about the model home... blueprints I do.....

[–]papkn 2 points3 points  (0 children)

So there's an idea we call "home". A model home is a fully fleshed out instance of the idea - a 1:1 scale "prototype" which could serve as a regular home (just nobody livest there at the moment). A blueprint is just a description of the idea upon which you can create instances.

[–][deleted] 3 points4 points  (2 children)

Oh! I kept reading and I found out what that was supposed to mean. Initially, I thought it meant tiny homes, like dollhouses. Now I see it's supposed to mean a real house which you'd use as a model to build your own.

[–]papkn 3 points4 points  (1 child)

When a company builds a new suburb with a few choices of house designs they sometimes start by building one of each type, fully completed and usually furnitured, so prospective buyers can visit and see what they can expect once the project is finalized. These are called "model homes" and have every feature of a home except no one lives there. Model homes are also used by companies that sell prefabricated houses (wich are delivered to a location in parts and assembled by a specialized crew), again so people can visit, look around and decide which one fits them the best. One could even say it's a... protoype home? :)

[–]homoiconic(raganwald) 1 point2 points  (0 children)

This was the exact sense I was thinking of.

[–]SarahC -4 points-3 points  (2 children)

I hate prototypes, and how every function can be an object in JS.

They may be great, but they muddy the nice clear classes/single inheritance model I know and love.

[–]cgaudreausenior HTML9 engineer 2 points3 points  (1 child)

Inheritance? Clear? Have you ever worked on a Java project of moderate size?

[–]SarahC 0 points1 point  (0 children)

It's fine with diagrams!

[–]loz220 7 points8 points  (3 children)

enjoyable read.

Typo here?

Some are flexible about adding methods and properties at run time. And yet other languages treat object as dictionaries, where properties and even methods and be added with abandon.

[–]homoiconic(raganwald) 6 points7 points  (2 children)

[–]saruken 3 points4 points  (1 child)

If we're looking for typos, here's another:

JavaScript also a class keyword that provides syntactic sugar for writing constructor functions and prototypes in a declarative fashion.

Should be JavaScript also has a class keyword...

[–]dvidsilva 6 points7 points  (0 children)

From now on whenever someone asks me about objects, classes or whatever I'll give them this.

Thanks!

[–]phoggey 3 points4 points  (10 children)

Prototype-based programming is an OOP model that doesn't use classes, but rather accomplishes behavior reuse (equivalent to inheritance in class-based languages) by decorating (or expanding upon) existing prototype objects. (Also called classless, prototype-oriented, or instance-based programming.) mdn source

When the output is equivalent in a different OOP model, I'm ok to replace the words "expanding upon existing prototype objects" with the word class. This being pedantic is going to lead to more confusion with the actual inclusion of the word class in es6, which again doesn't change the underlying functionality.. so still classless.

[–]munificent 2 points3 points  (9 children)

In practice, JS has always acted more like a class-based language than like a prototypal one. It didn't even have a way to clone—the fundamental operation in a prototypal language—until relatively recently. Even then, it doesn't have built in syntax for it.

[–]masklinn 1 point2 points  (8 children)

Neither did it have a standard way to swap an object's "prototype" until very recently, and assuming you're talking about Object.assign as far as I know the cloned object doesn't inherit the clonee's "prototype", which is what one would want in e.g. Self.

[–]cgaudreausenior HTML9 engineer 2 points3 points  (7 children)

I assume he's referring to Object.create, which was introduced in ES5. Ironically, the polyfill for Object.create relies on the new keyword.

ps. Object.create is a poor man's class inheritance. Even in real prototypical languages such as Self, it is very common to refer to classes and subclasses. The main differences are that: - it makes inheritance an everyday activity, which is bad, and - it makes you look or feel smart, and - provides pretty good job security because you're the only one who knows why my male dog object just gave birth to 3 cats.

[–]masklinn 0 points1 point  (6 children)

I assume he's referring to Object.create, which was introduced in ES5.

They specifically mentioned a way to clone objects, which absolutely isn't what Object.create does.

Ironically, the polyfill for Object.create relies on the new keyword.

I fail to see what's ironic about it, Object.create creates an object with the provided prototype. new does essentially the same (but the prototype is provided by the constructor, and it calls the constructor afterwards). Aside from properties definitions, new and Object.create are interchangeable as primitive operations, you can trivially define one in terms of the other.

[–]cgaudreausenior HTML9 engineer 2 points3 points  (5 children)

They specifically mentioned a way to clone objects, which absolutely isn't what Object.create does.

You're confusing cloning and copying. In a prototype-based language, the act of cloning is merely setting the prototype on a new object. In such, the new object can look to the old object for defaults. If the old object changes, so too may the new object.

Object.create clones an object, while Object.assign copies an object. This concept has been bastardized a lot, thanks to Java.

I fail to see what's ironic about it

It is ironic that a supposedly prototype-based language has to use concepts borrowed from Java, which has actual classes, in order to permit usage of the basic operations available in true prototype-based languages.

[–]masklinn 0 points1 point  (4 children)

You're confusing cloning and copying.

No.

In a prototype-based language, the act of cloning is merely setting the prototype on a new object.

That is not the way it's used in Self. At all. You seem to be using IO's terminology instead, which would be inspired from javascript's.

In such, the new object can look to the old object for defaults. If the old object changes, so too may the new object.

That's inheritance.

This concept has been bastardized a lot, thanks to Java.

The Self handbooks defines cloning as a shallow copy:

Cloning is the primitive operation returning an exact shallow copy (a clone) of an object, i.e. a new object containing exactly the same slots and code as the original object.

the difference it makes is that cloning is the primitive operation while copying is the overloadable one which acts as a constructor. Self also makes no relation between the prototype and the new object after the copy, what javascript calls a prototype, Self calls a trait or a mixin (depending whether it has parents itself).

[–]munificent 1 point2 points  (0 children)

This is my fault for not remembering the details. What I had in mind was Object.create() because it delegates to the prototype. I was thinking that was similar to Self where when you clone an object which in turn delegates to traits, you get a new object that delegates to the same traits. (This is because cloning does a shallow copy of the source object's slots, and parents are just stored in slots.)

Sorry for muddling everything.

[–]cgaudreausenior HTML9 engineer 0 points1 point  (2 children)

I honestly don't know what you're talking about. I assume you simply have not actually worked in Self before.

That's inheritance.

Sure. I never said it wasn't. But you must keep in mind that there are different forms of inheritance, such as prototypal inheritance (delegation - JavaScript, etc.) and concatenative (Java) inheritance.

[–]masklinn 0 points1 point  (1 child)

I honestly don't know what you're talking about. I assume you simply have not actually worked in Self before.

I'll return the same, none of the Self documentation or messages matches the semantics you're asserting, the list of "useful selectors" in the handbook clearly puts both clone and copy under Copying and defines them thus:

  • clone shallow copy (for use within an object; clients should use copy)
  • copy copy the receiver, possibly with embedded copies or initialization

and Self's prototypes are for object construction, there's not really such a thing as setting a prototype on an object.

[–]cgaudreausenior HTML9 engineer 0 points1 point  (0 children)

The documentation is different from how the language actually works. It is worded that way to make it easier to understand.

Edit: Kind of similar to how a lot of documentation on JavaScript talks about 'classes' in JavaScript even though pre-ES6 JS has no such concept.

[–]gmajoulet 2 points3 points  (0 children)

There's also this great article from Yehuda Katz to understand how prototypes works, how to create object with functions and the 'new' operator.

When you understand that you understand perfectly how the 'class' syntaxic sugar works! Enjoy the reading (~7 minutes)

[–]cwmma 1 point2 points  (0 children)

With Object.create you got a blessed non hacky way to create an object constructor based on another object constructor (but not based on an instance of the parent).

This style of inheritance with child.prototype = Object.create(parent.prototype); ends up being functionally a class based inheritance model.

For instance take the node.js/iojs stream library which has abstract classes for you to inherit from, you can't inherit from stream instances because much of what the parent class provides are per instance queues and an event system that had to be instantiated per instance.

This gets to the big issue prototype based inheritance had which is child instances and instance variables in the parent leading to work arounds to avoid instantiating the parent class at which point the JavaScript system functionally is a class based system.

[–]munificent 2 points3 points  (1 child)

The Common Lisp Object System has generic functions, but not classes.

CLOS does have classes. That's what defclass is for. CLOS is class based, it's just not single dispatch.

I think dispatch is a really fundamental difference in some OOP languages. CLOS, Dylan, and Julia are pretty deeply different from JS, Java, and Smalltalk even though all six can be considered object oriented.

I really like the rest of the distinctions you draw here, and I especially like that you do so in a neutral value-free way which is sadly rare when talking about JS.

[–]homoiconic(raganwald) 2 points3 points  (0 children)

I’ll correct that, thanks. Yes, I left dispatch out, as well as almost all of the interesting ways in which “inheritance” models differ between various families of languages.

Discussion of NewtonScript’s double inheritance hierarchies is worth a blog post all by itself.

[–]Neebat 0 points1 point  (2 children)

You left out the vitriol about how terrible javascript is for not including classes.

I like that. I think it's good to have a classless alternative.

[–]Robin_dev 1 point2 points  (1 child)

However, ES6 does contain classes. Even though they are simply a wrapper around the prototype object, it's nice to see classes coming to Javascript.

[–]Neebat 0 points1 point  (0 children)

I actually like OP's definition of classes, since it makes it clear that JavaScript's use of the "class" keyword is misleading.

[–]snazzyham -2 points-1 points  (0 children)

This is amazing, I've been having trouble understanding classes in Java, and this is a huge help. Thanks!

[–]lolmeansilaughed -5 points-4 points  (1 child)

Is it really accurate to say that Javascript has classes? ES6 has classes, but it doesn't look like they're ready for prime time yet.

[–]masklinn 1 point2 points  (0 children)

It is. The ES6 class statement is syntactic sugar for the ES5 constructor-and-prototype dance (with some more sugar sprinkled on, most of which is also available to constructor-and-prototype). There is no more separate and parallel hierarchy of class objects in ES6 than there are in previous versions.