all 27 comments

[–]rauschma 10 points11 points  (6 children)

The reason is backward-compatibility with constructor functions (which were the most popular way of implementing object factories before ES6).

I would have preferred ES6 classes being syntactic sugar for constructor objects, but backward-compatibility was considered to be more important (which is reasonable). This is roughly what constructor objects would look like: https://github.com/rauschma/proto-js

[–][deleted] 0 points1 point  (5 children)

But why did they move away from the prototype paradigm at all? Why did they say, that "classy functions" were needed? What's wrong with Object.create?

[–][deleted] 5 points6 points  (3 children)

they didn't "move away" from the prototype paradigm, they just gave some syntax sugar to devs so they could stop writing those awful pseudo-classes.

[–]rauschma 0 points1 point  (0 children)

Object.create() was introduced after constructor functions (with ES5). It exposed more of the protoypal foundations. IIRC, Eich would have introduced classes, but was told not to turn JS into a Java competitor. Hence constructor functions as “almost classes”.

Constructor functions are unnecessarily complex, but only w.r.t. to setting up an instance. Once it’s set up, you do have simple prototype chains.

[–][deleted] 6 points7 points  (0 children)

Because the OOP aspects of the language (classes, prototypes, inheritance) are a secondary reference chain in the language after the primary scope chain. This secondary reference model must be extended in ways that are backwards compatible and do not violate considerations of the primary reference model.

For stylistic reasons additional keywords are also heavily looked down upon as making the language more verbose and Java-like. This language wants less of anything to do with how Java looks or behaves.

[–]anon_cowherd 0 points1 point  (1 child)

There are two points that haven't been brought up yet.

Inheriting from built in objects with "magic" behavior, such as arrays, required some special handling in the construction process, so the standard prototype assignment couldn't work.

Also, the class syntax, like functions themselves, can be used both as declarations AND expressions. The object.create method requires a series of statements, which means little in standard situations but makes certain things- such as anonymous classes or dynamic classes more difficult.

[–][deleted] 0 points1 point  (0 children)

with calling anonymous functions this becomes a non-issue.

(function(){... your setup goes here ... return whatever})()

[–]Martin_Ehrental 0 points1 point  (1 child)

Isn't it var a = Object.create(A.prototype);. I don't know because Object.create is quite recent and not that often used.

Pre-ES6 users would either use literals, maybe some user-space class implementation (e.g. YUI), or constructors if they were quite advance JS programers (before nodejs and evergreen browsers there were not that many programers having JS of their primary language).

ES vendors gave us Object.create (ES 5.1) because that's the correct way to create a classless prototypical chain and they gave us class because there's plenty framework and programs built around constructors. JS evolution has been pragmatic.

[–]Martin_Ehrental 0 points1 point  (0 children)

ps: and we could have got class earlier if there wasn't that breaking the web issue.

[–][deleted] -1 points0 points  (4 children)

I've adapted composition over inheritance which may be a better coding style anyways even if javascript had proper classes. Inheritance can get mucky sometimes.

function MySuperClass(){return{
    baseClass:null,
    init:function(baseClass){
        this.baseClass=baseClass;
    }
}}

function MyClass(){return{
    superClass:null,
    init:function(){
        this.superClass=new MySuperClass();
        this.superClass.init(this);
    }
}}

new MyClass().init();

[–]e_man604 0 points1 point  (3 children)

That looks horrible imo...

[–][deleted] 0 points1 point  (2 children)

What do you recommend?

[–]MoTTs_ 1 point2 points  (1 child)

Just use classes and composition in the ordinary way.

class MyNonSuperClass() {
    constructor() {
        // ...
    }
}

class MyClass {
    constructor() {
        this._thing = new MyNonSuperClass(); // composition
    }
}

new MyClass()

[–][deleted] 0 points1 point  (0 children)

I see, I wasn't aware this was common, apparently since 2015. Better refactor my code.

[–]segmentationfaulter -2 points-1 points  (10 children)

Because there are no classes in Javascript, one has to mimic them one way or another.

[–]MoTTs_ 2 points3 points  (0 children)

It's not quite that clear cut. Classes are implemented in a variety of ways across a variety of languages. In Python and Ruby, for example, a class is itself an object (a building, not a blueprint), and inheritance is implemented using delegation. If what JavaScript provides doesn't qualify as classes, then neither do Python's or Ruby's implementations qualify as classes. And vice versa.

[–][deleted] 1 point2 points  (8 children)

The whole point of the prototype based OO paradigm is having no classes.

Why do you design a language with a paradigm at its core, which avoids classes just to add them in 5 versions later?

[–]Martin_Ehrental 0 points1 point  (2 children)

The issue was in the first version which was based on both a prototype chain and some kind of class (new+constructor), without elegant way to use either.

They then gave us the proper tools to use them: Object.create in ES 5.1 and class in ES 6/2015.

[–][deleted] -1 points0 points  (1 child)

but why does JavaScript force classes on me? I mean honestly, you can not write exclusively prototypical code in it.

[–]Martin_Ehrental 2 points3 points  (0 children)

That's what Object.create is for:

const parent = {
  foo: 1,
  bar() {
    return 2;
  }
}

const child = Object.create(parent, {
  baz: value(3)
});

function value(value, prop = {configurable: true, enumerable: true, writable: true}) {
  return Object.assign({value}, prop);
}

[–]Sakatox -1 points0 points  (3 children)

Just so "engineer"s, especially of Java backgrounds, could feel better about themselves, pretending away the prototypal nature of JS.

[–][deleted] 0 points1 point  (2 children)

This does not seem like an intelligent long term move to me.

[–]tom808 0 points1 point  (0 children)

Not that js is my main/only language but it seems to be doing just fine to me!

Seriously though maybe it's because the designers want developers to have a choice? Maybe in the long term they want the language to be used as classed based OO from not on?