Hacker News new | past | comments | ask | show | jobs | submit login

This makes sad, as Douglas Crockford said in this recent talk

> The prototypal school has a lot of advantages particularly compared to the classical school

> So in the classical school you have to create a classification of all the objects that are likely to be in your system. And, it's a lot of work to figure out what they all are and identify them and what their characteristics are and so on and then you have to determine how they are all related to each other, what’s going to inherit from what, what’s going to implement what, what’s going to interface with what, and that’s really complicated. And it usually happens at the beginning of the project before you fully understand what all this stuff means. So it’s likely your going to get the taxonomy wrong. It’s inevitable.

> And then you’ve got two hard choices. One is you have to live with a broken taxonomy and if you do that then with each new class you introduce things get weirder and weirder because everything’s wrong, or you have to refactor and refactoring is hard and it’s error prone and it’s another world of hurt.

> Those are your two choices and people who grew up in the classical school assume that’s just the way life is so no sense in complaining about it since that’s life.

> But in the prototypal school you don’t do any of that. You just make an object, if you don’t like the way it works you make another one and that is literally it.

> So you can tell people from the classical school “You don’t have to do all of that” and they go “Yea, I hear ya, but you still have to do it” and you say “no, you don’t have to do it” and they go “yea, yea, yea” (blowing you off)

> And so that’s why I think classes in ES6 are a bad part because they lock you into that paradigm.

> applause

> So when you’re locked in a paradigm like that, when you can’t see past it, you just have no understanding how miserable you are. And you’ll never know until you change your model

from https://www.youtube.com/watch?v=bo36MrBfTk4#t=28m50s




I don't mean to be argumentative (being argumentative on HN is so passé), but what you just quoted is so full of shit that I feel like someone is obligated to comment.

In the prototypal model — as it exists in JavaScript — you do do all of that. You make a series of prototypes that you intend to use in your application, and those prototypes (or classes), serve as the effective taxonomy for many of the objects you're making in your app.

Classes in ES6 are prototypes. They don't lock you into any such Java-esque paradigm unless you're going to be willfully ignorant about them.

Please don't repeat baloney just because Crockford said it.

---

For example, to be concrete:

    class Crockford {
      speechify() {
        return "...you're going to get the taxonomy wrong. It’s inevitable.";
      }
    }
A class. A terrible, inflexible, prototype-destroying, paradigm-locking-in, JavaScript class. Eww, gross.

But wait! What's this?

    Crockford.prototype.speechify = function() {
      return "...the shape of an object can change at any instant, because \
             someone can fiddle with the prototype.";
    };
You can have your classical cake and eat prototypal cookies too. Because in any decent dynamic language, the two concepts are synonymous.


It's not baloney IMO. As someone who's coded C since the 80s and C++ since the 90s I find JavaScript massively freeing.

In C++ (and similar classical languages) in order to be able to pass in different implementations of a class you need to create a base class or interface. You don't need to do this in JavaScript.

In JavaScript you can build objects on the fly. In fact he goes on to say

> so I used to think that the important thing in JavaScript was prototypal inheritance I now think it is Class Free object oriented programing. I think that is JavaScript’s gift to humanity. That’s the thing that makes it a really interesting important language, is that it did that. That we can use functions in order to create objects and it simple and elegant and powerful and fast...

And it's true. Look at the mocking libraries for JavaScript. They're sooooooooo much easier to write than anything for classical languages because it's so easy to do in JavaScript. In my own experience I have a mutli-user networking system written in JavaScript and a library in C#. To reimplement the same things in JavaScript in C# is a huge amount of code bloat. I have to make classes and meta classes and all kinds of other indirection just so I can make an Event system that is generic. In JavaScript that's 2 or 3 lines

That we don't actually need all the structure to get shit done is what people are finally coming to realize.

The problem with 'class' in ES6 is that it will prevent people from learning this new, easier, faster, simpler way of working because instead they just bring the classical baggage to JavaScript. That's in fact what most programmers from classical languages do. It's what I did for years until I started actually grokking JavaScript. ES6 "class" will only make it take longer for people to actually get pass their old ways.


> As someone who's coded C since the 80s and C++ since the 90s I find JavaScript massively freeing.

I've gone back and forth between dynamic and static and strict and loose in every combination and I don't find the dynamic/loose to be particularly freeing anymore. The problem is you can't really rely on anything. It doesn't so much as solve the problem that Crockford is talking about, it just moves it somewhere else. You don't have to refactor but you're going to end up with two (or more) different things that exist at the same time instead of one.

> Look at the mocking libraries for JavaScript. They're sooooooooo much easier to write than anything for classical languages because it's so easy to do in JavaScript.

This is a great point and it's a perfect example of the advantages and the horrors of the JavaScript model. A mock is supposed to be an object that does something completely different (typically nothing) but otherwise looks and functions like the real thing. Maybe just in one slight exceptional way. JavaScript makes this easy. But it also makes it easy to make those same changes outside of mocking and tests and that is just debugging hell waiting to happen.


You can write bad spaghetti code in any language. You avoid that with style guides, linters, and code review.


I don't see how strict typing couldn't fit at the end of your list as well.


It could but some of us have had the experience of massive productive increases in JavaScript over our decades of experience in statically typed languages.

And note I'm specifically calling out JavaScript. Other dynamic languages IMO haven't provided the same benefits because they're still following old models.

When you truly grok JavaScript and stop trying to use it like your other languages it really starts to shine. It's not perfect but it is different.


> And it's true. Look at the mocking libraries for JavaScript. They're sooooooooo much easier to write than anything for classical languages because it's so easy to do in JavaScript. In my own experience I have a mutli-user networking system written in JavaScript and a library in C#. To reimplement the same things in JavaScript in C# is a huge amount of code bloat. I have to make classes and meta classes and all kinds of other indirection just so I can make an Event system that is generic. In JavaScript that's 2 or 3 lines

That does not follow from what you quoted, and what you quoted is a non-sequitur to start with.

What you're raving about can be achieved just as easily in any dynamically typed language. Hell you probably get 80~90% of that in a structurally typed language (OCaml objects, Go).

> In JavaScript you can build objects on the fly.

Which you can do in many other languages, including statically typed ones. Here's an object in Ocaml:

    # let s = object
        val mutable v = [0; 2]

        method pop =
          match v with
          | hd :: tl -> 
            v <- tl;
            Some hd
          | [] -> None

        method push hd = 
          v <- hd :: v
      end
And that's statically typed.

> The problem with 'class' in ES6 is that it will prevent people from learning this new, easier, faster, simpler way of working because instead they just bring the classical baggage to JavaScript.

That's patent nonsense, not to mention ES6's class shortcuts apply to object literals as well, the only thing the class statement does is remove the bullshit and mostly useless boilerplate Javascript demands when creating a reusable prototype due to it being a garbage language, and its "prototypal" object system being there not because it's good and going to save the masses but because it was the easiest way to have an object system working in a week. It's just a sad and pitiful shadow of Self's object system from which it draws so little you have to know the relation's there to find it.


> That we don't actually need all the structure to get shit done is what people are finally coming to realize.

Getting stuff done until the code base grows and others have to adapt or build up on the code you've written : the idea of bringing in structure is to encode knowledge about the problem you are solving and keeps it all maintainable (admitted, if done right).

> In C++ (and similar classical languages) in order to be able to pass in different implementations of a class you need to create a base class or interface.

And that is a good thing IMHO, see above. However I agree that, particularly in C++, an interface definition is very verbose. Unfortunately it has no pure Interface concept.


You can always use pure virtual classes, but requires discipline and virtual inheritance.


As a javascript programmer, I have perceived es6 "classes" as nothing but syntactic sugar. They should just construct the equivalent constructor+prototype combo. You can still create anonymous objects quickly, and use any object as prototype for another.


> As a javascript programmer, I have perceived es6 "classes" as nothing but syntactic sugar.

That's basically what they are.

> You can still create anonymous objects quickly, and use any object as prototype for another.

Hell you can create anonymous objects even faster with ES6 since object literals also get the short method notation and computed properties.


Yes, but let's admit it, the presence of classes will inevitably lead to their ever-presence, if only for the fact that they are what most people coming from other languages are used to.


The absence of class already leads to their ever presence, each project simply reimplements its own instead of using the built-in syntactic sugar. The class sugar is simply a way for the creation of (prototype + constructor) pairs not to be a pain in the ass, nothing more and nothing less.


" They're sooooooooo much easier to write than anything for classical languages because it's so easy to do in JavaScript."

You can do that in a language with classes and even one with optional types e.g. you can use jasmine perfectly well to mock typescript objects (because they are just JavaScript dynamic objects)

" I have to make classes and meta classes and all kinds of other indirection just so I can make an Event system that is generic."

I remember reading Gilad Bracha saying somewhere that enabling exactly this kind of system was exactly one of the use cases for Dart which is class based with optional types. You can have your cake and eat it too!


I think you're confusing this new Chrome-only thing with ES6 classes that just saves you from using a library to create constructor/prototype objects. In ES6 "class" is just a keyword that makes it easy to contruct objects that are very typical in day-to-day JS. Inheritance is already a thing that happens.


I'm not. See above, "class free object oriented programming". You don't need prototypical inheritance to have inheritance in JavaScript. Crockford gives examples. You don't need the "class" keyword. All it's going to do is steer people in the wrong direction.


Can you give an example of inheritance without prototypes in javascript?


from D.C.

    function base(spec) {
        var that = {},
            member,
            method = function() {
                // spec, member, method
            };
        that.method = method;
        return that;
    }

    function derived(spec) {
        var that = base(spec),
            member,
            method = function() {
                // spec, member, method
            };
        that.method = method;
        return that;
    }
I'd suggest you watch the talk linked above for this stuff in context.


That is not inheritance. `instanceof` doesn't work. There would be no way to know that an object from derive dis of the type of base.

That's also very memory inefficient. The method function gets made for every instance. With prototypes there would be only 1 function in memory. This stuff matters at scale.


Watch the talk.

You've got a gig of ram in your pocket. Memory doesn't matter for 99.99999% of apps. The memory taken by your objects isn't where your memory goes. It goes to images and other big stuff. A few extra bytes per object isn't going to kill you. Optimize for programmer time not memory, especially not in memory on things that don't matter.

Why are you using "instanceof". The whole point of inheritance is you shouldn't have to ask. If you are asking your doing it wrong


and then how do you implement super with your system? because that's the point of prototypes,the fact that you're not overloading methods but you have access to the prototype chain.much harder to do with your method.


You shouldn't need access to the prototype chain. Accessing that chain is an anti-pattern.


no it isn't,that's how you implement "super" in javascript.


Check out Daniel X. Moore's `{SUPER: SYSTEM}`. http://stackoverflow.com/a/3731253


> You just make an object, if you don’t like the way it works you make another one and that is literally it.

This is, like jashekanas eloquently puts it, so full of shit.

You're still creating a bunch of objects. Unless you are a mashocist (or a sadist, if other people have to maintain your code), you are still going to want to reuse methods between those objects.

Once you do that, you have to have some organization between what gets reused how. Sure, prototypes give you more freedom to define different ways of organizing and reusing behavior across objects. In practice, single-delegation actually works pretty well most of the time.

> So you can tell people from the classical school “You don’t have to do all of that” and they go “Yea, I hear ya, but you still have to do it” and you say “no, you don’t have to do it” and they go “yea, yea, yea” (blowing you off)

It's not that you don't have to create a taxonomy in JS. It's, "First you have to conceive and implement the very idea of a taxonomy itself. Then you get to use that to create a taxonomy."

You need to reuse code somehow. Figuring out a scheme for doing that is metaprogramming. JS basically says, "Well, you have to do this metaprogramming before you can get to the task you actually care about."

Using classes (or any other baked-in reuse scheme like parent slots in Self) just means the language has done the metaprogramming for you and you can use it out of the box.

The flexibility JS gives you is nice when the language's built-in mechanisms for code reuse aren't a good fit. But, so far, most homegrown code-reuse-systems don't seem to be that much better than what classes (with maybe some mixin or trait special sauce on top) provide.


> You're still creating a bunch of objects. Unless you are a mashocist (...) you are still going to want to reuse methods between those objects.

Aaaaaaand solution for that doesn't have to be a class (or something pretending to be a class), but for example a collection of functions/methods that you attach to an object, so you for example assign behaviour to data. This is something that Reginald Braithwaite for example advocates.


> a collection of functions/methods that you attach to an object

Yes, that's what I meant when I said you have to design your own metaprogramming layer. You can do that. Just like you can invent your own class or prototype layer in C if you like.

The question is "Is having to do that a compelling feature for the language?" Are user's metaprogramming needs so diverse that the language should punt this problem onto users?

I don't see much evidence that this is the case. Most JavaScript libraries end up reinventing something that's within spitting distance of classes and single inheritance, maybe with a dash of mixins. All of that re-invention is a huge waste of engineer time.


That's called "composition over inheritance" and OO languages are perfectly capable of it.


I don't get it. I know how prototypes in Javascript work, I can agree that you get a certain degree of flexibility that you don't get with class-based languages, which sometimes is useful, however people are still modeling classes in Javascript and people blaming education have the burden of proof - show problems that could have been solved with classes, but that were solved with a "class free" design instead.

And heck, I'll go further - in my mind, both class-based and prototype-based OOP, at least as present in Javascript or other mainstream languages, sucks because it mixes data with behavior and still suffers from the expression problem, because while you can take any object and modify it for a new interface, a process called monkey patching, that's just a terrible way of doing it.

OOP as a means to achieve polymorphism is simply inadequate for many use-cases. Sometimes it is much better to have type-classes (or similar, like protocols in Clojure). So you know, comparing 2 ways of dealing with OOP, misses the point that OOP on the whole is not enough, even broken as some would say.


> I can agree that you get a certain degree of flexibility that you don't get with class-based languages

That's not even the case. Not in Javascript anyway. The only thing you get is not having a separate hierarchy of class objects.


Most class based languages won't let you inherit from an instance, and many won't let you use the same techniques you use to inspect or constrain instances to inspect or constrain classes.


>But in the prototypal school you don’t do any of that. You just make an object, if you don’t like the way it works you make another one and that is literally it.

Yeah, which goes to show you shouldn't listen to Douglas Cockford.

First, what he describes is playing in a REPL at best. You don't just "make another [object] if you don't like the way the fist one works" when you write a program, unless you write a structureless blob. You still have to think about your objects and/or inheritance chain, be it prototypal or not.

Second, ES6 classes are nothing more than syntactic sugar over barebones prototypal inheritance.

Third, you already do all that stuff in JS. You have to write a lot of boilerplate code (and usually everyone does a slightly different version) to get the same end result.


I feel like the concepts are being abused here. Prototypical — at least in my understanding — refers to a mechanism of inheritance or delegation, and not as Crockford uses the term to the way you build your objects. Confusingly, JavaScript didn't even have prototypical inheritance until relatively recently, because even though every object had a prototype, it couldn't be set or changed on an individual basis, but was determined solely by which Constructor (read: Class) that created it, which made JavaScript's inheritance mechanism essentially indistinguishable from the classical, albeit with more obscure nomenclature.


ES6 classes are just syntactic sugar for constructor/prototypes like we write them today. You can mutate them as much as you like.


not in SoundScript they aren't


Pretty sure they still are syntactic sugar for prototypes, just like in ES6. But SoundScript enforces that you cannot modify prototypes. There's not really a problem with that, it's doing it for speed. So it's not for your average Javascript app where performance doesn't matter as much.


although i agree somewhat, prototypal inheritance does nothing to help solve the taxonomy.

the article below i think explains the situation much better: https://oleksandrmanzyuk.wordpress.com/2014/06/18/from-objec...




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: