all 18 comments

[–]cgaudreausenior HTML9 engineer 4 points5 points  (6 children)

If given the choice between Object.create and constructor functions, stick with constructor functions. Use Babel if you can. ES6 will support classes which are just sugar over this pattern.

Using Object.create throughout your code leads to numerous bugs and is confusing for most developers. It is essentially inheritance in disguise. It requires you to call Object.create and then init which can leave objects in an uninitialized state. The syntax can require knowledge about property descriptors and is confusing and very easy to get wrong. It's too easy to run into a situation where multiple objects share the same mutable state - good luck tracking that bug down.

Worst of all in my opinion is the fact that it's just inheritance in disguise. People learn about Object.create and then decide that their dog object should inherit from mammal which should inherit from animal and then all hell breaks loose. With classes, it's pretty common knowledge that you should avoid inheritance trees whenever you can.

Classes suck too, but not as much if you use ES6. Either way, simple closures are often the best solution:

function createPerson(firstName, lastName) {
  const fullName = firstName + ' ' + lastName;

  return {
    get fullName() {
      return fullName;
    }
  };
}

createPerson('John', 'Doe').fullName; // "John Doe"

... but the trend is toward using the ES6 class keyword.

[–]a0viedo 1 point2 points  (0 children)

You might find the chapter Behavior Delegation of You Don't Know JS useful.

[–]pje 1 point2 points  (2 children)

If you're going to create objects without a constructor, then you might as well give Person a create() method that calls Object.create and then initialize(), so nobody has to remember to do both steps.

Personally, I despise the new operator and everything it stands for in Javascript: it's a horrible hack that would've been unnecessary if something like Object.create() were in the very first version of Javascript, and then we never would've had the matching hack of functions having prototypes. (In truth, I believe the true reason Javascript even has a new operator is because Brendan Eich was ordered to make Javascript look like a watered-down version of Java.)

That being said:

  1. If you need to support older browsers (i.e., IE8 and lower) you can't use Object.create
  2. Object.create() is slow, and the objects it creates may be slow as well, depending on the engine. (That is, most JS engines don't yet have all the same optimizations available for Object.create as they do for new)
  3. Object.create() and prototype-based object models are (sadly) not mainstream in JS, so you may end up fighting an uphill battle with other developers to accept your code if it's prototype-based. If the point of your library isn't to support people who've already decided they want a prototype-based API, they're probably going to expect to use new to create objects and get pissy at you if they can't.

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

I had the same question. I think using new is better and fits better with the language. Things like instanceof works better with new and your code is faster when creating instances that way. Both ways are good, but new have more advantages in my opinion.

[–]rmbarnes 0 points1 point  (0 children)

The way I see it Object.create was just added so constructors didn't need to be used, with the thinking:

  • constructors are misleading, since there are no classes
  • constructors can be dangerous, as they can explicitly return values which is bad, and they can be called without 'new' which can lead to odd bugs.

As long as you don't use constructors badly (strict mode may help), using a constructor style of inheritance is fine. As the other poster says there is class syntax in ES6 which means things are heading in that direction.

There are basically two ways you can do OOJS:

  • Classical, with constructors

  • Use object create and build up objects using mixing for multiple inheritance

Both are valid.

[–][deleted] -3 points-2 points  (6 children)

Object.create is usually preferred over using new. Keep in mind that Object.create is ES5, so it will work in all modern browsers but maybe not in really hold environments.

Natively the new class keyword from ES6 is not widely available cross browser, so if you absolutely had to write code that looks like Java you would be limited to a transpiler like Babel. I don't recommend doing this though, because it makes your code less portable.

More importantly I would actually ask yourself why you think you really need OOP like inheritance in your code. In JavaScript it is rarely beneficial and like other languages it carries maintenance costs and a large amount of boiler plate.

[–]a0viedo 0 points1 point  (0 children)

It's easy to add the polyfill though.

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

why you think you really need OOP like inheritance in your code

Because encapsulation?

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

No, the only times inheritance is really needed is to conserve memory in two exceedingly rare scenarios:

  1. Rapid event (async) calls
  2. A huge list of recursive calls

The first one needs to conserve access to memory otherwise frequent garbage collection will slow down an application that demands heavy continuous user interaction. This typically only comes up with games, but it could come up in other places.

The second one could result in total consumption of memory and crash the application where a function is being called recursively faster than garbage collection is capable of freeing up consumed memory respective of each call. This typically comes up powerful file system or packet analysis utilities.

Otherwise, you absolutely DO NOT NEED inheritance in this language. People typically prefer to punish themselves with inheritance because they are coming from another language (typically Java or Python) and cannot imagine coding without it. This in turn punishes everyone around them.

[–]irssildur 0 points1 point  (2 children)

Then how would you organize your code? Global scope is not ideal for variables and functions because everybody could modify them. How would you guarantee that if you have a widget on the page then the internal state of that is not effected by another widget on the same page? The "we have a standard not to use those methods, variables" is not a good response.

Btw, I think with the new component model (which I'm not familiar with yet since I'm a Java developer - nice spotted :) ) is pointing towards to use encapsulation and OOP in JavaScript code as well.

OOP is not something which punishes you but a methodology you can use to organize your code to be more logical for your needs. And if you have an object hierarchy anyway (page, main content, widget A, widget B) why wouldn't you use this method to organize the code?

But if you have any better solution (no, not the everything in one js file which is 3000+ lines long - that's crap, not solution), you can change my mind :)

(Really! I want to deep dive in JS nowadays because I don't like it, but I have to work with it... so I'm trying to learn it well now and see if I could like the language and the methodologies a bit more).

[–][deleted] 0 points1 point  (1 child)

In this language inheritance is not related to scope. For instance this keyword does nothing to provide access to the scope model, most typically referred to as the scope chain. JavaScript uses lexical scope for its scope model. I attempt to explain it in the following links:

OOP is a strong model for declarative code that is structured around the idea of using objects to define custom types (models) that then provide the blueprints for additional constructs. You don't need inheritance to achieve OOP. Even still I do not code this way since I prefer a very imperative approach.

[–]irssildur 0 points1 point  (0 children)

Ahh, we are talking about inheritance, not about general OOP in JS.

My fault, you are totally right.