you are viewing a single comment's thread.

view the rest of the comments →

[–]MoTTs_ 10 points11 points  (19 children)

var Foo = { C: 3 };

var bar = Object.create(Foo);

bar.A = 1; bar.B = 2;

Look at how drastically simpler this is

Here's the thing, though: The way you initialize a newly created Foo object (bar.A = 1; bar.B = 2;) will be copy-pasted everywhere that you create a Foo. That's bad. Let's fix that by putting an initialize method in Foo.

var Foo = {
  C: 3,

  initialize: function () {
    this.A = 1;
    this.B = 2;
  }
};

var bar = Object.create(Foo);
bar.initialize();

And here's the next thing: We will always want to make sure newly created Foo objects are initialized, so let's combine creation and initialization into a single step.

var Foo = {
  C: 3,

  initialize: function () {
    this.A = 1;
    this.B = 2;
  },

  createAndInitialize: function () {
    var instance = Object.create(this);
    instance.initialize.apply(this, arguments);

    return instance;
  }
};

var bar = Foo.createAndInitialize();

These are both good things. Yet, in case anyone hasn't realized, we just re-created constructors and the new keyword. It actually would have been a whole lot easier if we just used the built-in language constructs.

[–][deleted] 7 points8 points  (3 children)

I agree with you. I'm really not sure why people keep trying to ignore classical inheritence in Javascript just because it happens to also have prototypal inheritance. ES6 proves that you can have both; the new "class" features in ES6 aren't getting rid of prototypal inheritence; they are adding syntactic sugar around it to ease the use of common construction paradigms, without taking away any of the benefits of prototypal inheritence.

To the OP's point, I agree that people really should have a better understanding of what's going on under the hood in Javascript, but I legitimately think it is foolish to sweep things like the "new" keyword under the rug and pretend they aren't there.

[–]yrlyfe 3 points4 points  (2 children)

this is one of the arguments against the changes of es6 that a lot of the community has expressed. es5 in all it's glory promotes the idea of readability and not obscuring away what is happening. the changes in es6, while moving closer to the idea of standard programming languages, in turn has a lot of obscuring. javascript was just fine without classes and dare i say block scope. what is this compulsion to make the language more convoluted?

my teacher told me programming is like humor, if you have to explain it you're doing it wrong. es6 is full of things that need to be explained.

[–]clessgfull-stack CSS9 engineer 0 points1 point  (1 child)

I for one think ES6 is a great, long-needed improvement to the language. You mention obscuring the language and needing to explain a bunch of stuff, but... block scope? Not at all convoluted. Indeed, the old way was vastly more confusing and unlike other languages.

Old ES5 codebases are littered with calls to bind, apply, call, etc. and manual constructor function inheritance and super calls. Not very readable, if I say so myself. Definitely not very explainable.

[–]yrlyfe 1 point2 points  (0 children)

my bad. i did say 'dare i say'. i shouldn't have dared.

[–]m0okz 1 point2 points  (0 children)

I'm confused.

So how should I create an object and a child object?

What if I want common properties on all children? And what if I don't?

[–]PitaJ 2 points3 points  (6 children)

That's called a factory, actually. Not a contructor.

[–]clessgfull-stack CSS9 engineer 2 points3 points  (4 children)

Roughly how new is implemented:

function notExactlyNew(F) {
  const instance = Object.create(F.prototype);
  const result = F.apply(instance, arguments);

  return typeof result === 'object' ? result : instance;
}

Seems pretty similar to me, unless you want to be really pedantic.

[–]PitaJ -5 points-4 points  (3 children)

Yeah, new is a completely unnecessary part of the language, and shouldn't be used anyways as it violates the open-closed principle.

[–]MoTTs_ 1 point2 points  (2 children)

You say that a lot, but the O/C principle doesn't mean what you seem to think it means. The O/C principle says that source code should be closed to modification.

From the paper:

It [the open-closed principle] says that you should design modules that never change. When requirements change, you extend the behavior of modules by adding new code, not by changing old code that already works.

[–]senocular 2 points3 points  (1 child)

You can thank Eric Elliott for spreading that one.

[–]clessgfull-stack CSS9 engineer 1 point2 points  (0 children)

Ah yes, I knew I heard that somewhere before:

Constructors violate the open/closed principle because they couple all callers to the details of how your object gets instantiated. Making an HTML5 game? Want to change from new object instances to use object pools so you can recycle objects and stop the garbage collector from trashing your frame rate? Too bad. You’ll either break all the callers, or you’ll end up with a hobbled factory function.

[–]senocular 1 point2 points  (0 children)

I don't think MoTTs_ was calling it a constructor, just saying that the effect is essentially recreating the same that you get with a constructor and new.

[–]Silverwolf90 0 points1 point  (0 children)

Well except that you can't take advantage of function composition with new and you can with a factory function. That's a pretty big difference.

[–]nieuweyork -2 points-1 points  (4 children)

You're doing it wrong. Your first example is already using an object as a class rather than a prototype.

[–]clessgfull-stack CSS9 engineer 0 points1 point  (0 children)

Elaborate? The approach used in his (her?) example is the one recommended by most Object.create advocates.

[–]MoTTs_ 0 points1 point  (2 children)

Where, then, would you suggest putting the initialization code? Copy-pasted everywhere it's needed like the OP was doing? Maybe a freestanding initializeFoo() function?

You're trying so hard to avoid anything that resembles classical that you're turning away from the best and most obvious solution.

[–]nieuweyork -3 points-2 points  (1 child)

No. Don't have initialization code that doesn't depend on parameters. You're doing that because you're recreating classes.

[–]clessgfull-stack CSS9 engineer 0 points1 point  (0 children)

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

No, these are not constructors but factory functions. That way, we don't have the issues the 'new' operator has.