4

I am new to JavaScript. I'm reading the section on "Parasitic Combination Inheritance" in the Professional Javascript for Web Developers 3rd Edition in Chapter 6. With the introduction of ES6 and a strong push to move away from "new" and deep hierarchies, is there a purpose to use the Parasitic Combination Inheritance pattern anymore?

What is used today? I feel like I am learning a bunch of patterns that are useless. I know people just use Object.create() and Object.assign() these days, so why even mention these inheritance patterns?

iSkore
  • 7,394
  • 3
  • 34
  • 59
Even Steven
  • 137
  • 6
  • 3
    At the risk of exposing my ignorance-- I have been developing with JS professionally for several years, and I have never heard of this. Furthermore, if I search it in Google, the first two posts I get are stackoverflow questions about it that appear to be from people reading the same book as you are... [here](http://stackoverflow.com/questions/16929353/parasitic-combination-inheritance-in-professional-javascript-for-web-developer) and [here](http://stackoverflow.com/questions/5467385/what-is-the-difference-between-parasitic-combination-inheritance-and-combination)... – Alexander Nied Oct 15 '16 at 04:21
  • Yes, I've seen these posts, however none of them answer my question of whether they are actually used today. I understand how it works, but definitely didn't memorize the pattern.. – Even Steven Oct 15 '16 at 04:39
  • 2
    Yeah, sorry, all I'm trying to get at is that it seems like the only time it ever seems to get mentioned is from people reading this specific book. Seems like maybe it's more of an academic thing than something in wide use, at least under that name. I don't think you should concern yourself with memorizing it. – Alexander Nied Oct 15 '16 at 04:41
  • _I know people just use Object.create() and Object.assign() these days, so why even mention these inheritance patterns?_ Why even mention them? Because they didn't exist the last time that book was updated, let alone when it was originally written. Looks to me like that pattern is now obsolete thanks to `Object.create`. – JLRishe Oct 15 '16 at 15:18
  • "*a strong push to move away from "new"*"- Huh? – Bergi Oct 15 '16 at 20:10
  • @anied There are many people using the pattern, only most of them don't know it's name (Or that there is a name at all) :-D – Bergi Oct 15 '16 at 20:12
  • @Bergi - fair point! – Alexander Nied Oct 15 '16 at 20:25
  • "strong push to move away from "new"" I'm not sure where you heard this, but classical JavaScript is not going anywhere, especially not with ES6 that makes it extremely simple to create classes and TypeScript that brings type safety into the JS world. I'd agree though that people are moving away from inheritance all together to favor composition whenever possible. – plalx Oct 16 '16 at 01:18
  • @JLRishe the book mentions Object.create before introducing this concept. It even goes into the inspiration behind the method. – Even Steven Oct 16 '16 at 06:12
  • @Bergi From what I've been reading, there is a strong push to use object literals and prototypal inheritance. This movement is largely thanks to Douglas Crockford and a few others in the industry. Deep inheritance has been strongly discouraged and there has been two major methodologies Object.create and Object.assign that are becoming the norm. Obviously as we know, Object.create uses the "new" keyword, but it is being strongly discouraged whenever possible. Maybe other can chime in and help elaborate what I'm speaking of. I'm certainly no expert, but this is what I've been reading. – Even Steven Oct 16 '16 at 06:20
  • 1
    @EvenSteven Yes, there are many patterns without `new` (including `Object.create`, which definitely *not* use the `new` keyword), but I'd say that currently ES6 classes are (or were) growing and are the norm, and those do rely on `new`. – Bergi Oct 16 '16 at 12:38
  • @Bergi Isn't the `bar.prototype = Object.create(foo.prototype); bar.prototype.baz = "whatever";` pattern literally Parasitic Inheritance ? The `Object.create ()` part creates an object, links it to another, and then you manually augment the returned object. Isn't this literally the same thing that happens with Parasitic Inheritance ? – doubleOrt Oct 04 '17 at 15:04
  • @Taurus Parasitic inheritance usually copies the object, or directly amends it (e.g. using `Object.assign`). And it does that to an instance, obtained from a factory function. It does not do any dynamic prototypical *linking* which keeps the relationship alive. – Bergi Oct 04 '17 at 15:11
  • @Bergi I was referring to the example [here](http://javascript.crockford.com/inheritance.html). This example is basically half the `Object.create()` polyfill I have seen, and the other half is similar to the part of the pattern I described in the other comment where you augment the object returned by `Object.create()`. And there is no copying in Crockford's example (or I am misunderstanding what you meant to convey), just an instantiation using `new` (which is basically a linking behind-the-scenes), and then an augmentation. – doubleOrt Oct 04 '17 at 15:29
  • @Bergi The `Object.create()` polyfill I am talking about is different than MDN's in that theirs creates an instance of `Object` and then sets that objects `[[prototype]]` to the object passed for the first parameter of `Object.create()`. The one I am talking about is where a function is created, its `.prototype` is set to the first argument of `Object.create()`, and then an instance of that function is returned. I don't think it makes a difference though, since both variations essentially return an object whose `[[prototype]]` is the object passed for the first parameter of `Object.create()`. – doubleOrt Oct 04 '17 at 15:35
  • @Taurus Re "*no copying*": that's what I meant by "or directly amends it". Notice that the `new` is optional in parasitic inheritance, as all the constructors explicitly `return` the object. Re "*I don't think it makes a difference*": it absolutely does! [\[\[prototype\]\] and `.prototype` are completely different things](https://stackoverflow.com/q/9959727/1048572)! – Bergi Oct 04 '17 at 18:44
  • @Bergi Sure, they are different, but one directly sets the `[[prototype]]` and returns that object. The othet sets the `.prototype` to the passed object, and returns an instance of the function created. In both cases, the result is the same: an object whose `[[prototype]]` is the passed object. – doubleOrt Oct 04 '17 at 19:34
  • @Taurus **No!** They are very different in the outcome. Setting the `.prototype` property - which is just another standard property - does not affect the prototype chain. – Bergi Oct 04 '17 at 21:09
  • @Bergi Yes, but setting the `.prototype` property of a function and returning an instance of that function does affect the prototype chain of the returned object. – doubleOrt Oct 04 '17 at 21:18
  • @Taurus Parasitical inheritance does not use that? – Bergi Oct 04 '17 at 21:23
  • @Bergi I am referring to [this](http://javascript.crockford.com/inheritance.html) example, it does create an instance from a constructor (therefore, an object that is prototype linked to another). And this is basically what `Object.create()` does, it creates an object linked to an object you pass to it. So in both cases, you get an object `[[prototype]]` linked to another (the one you want to extend), and then you augment that object by manually adding properties and methods to it. – doubleOrt Oct 04 '17 at 21:50
  • @Taurus No, it does not create any instances, all it does is create plain objects and `return` them! [The `new` keyword](https://stackoverflow.com/q/1646698/1048572) doesn't change that (see also [this example](https://stackoverflow.com/q/9304206/1048572)) and [actually should not be used there at all](https://stackoverflow.com/q/9304473/1048572). – Bergi Oct 04 '17 at 22:01
  • @Bergi A plain object is an instance of `Object`, isn't it ? – doubleOrt Oct 04 '17 at 22:02
  • @Taurus Yes, and does therefore not have a special [[prototype]] link. Very much unlike an object created by `Object.create` (unless you pass the `Object.prototype` object, of course). – Bergi Oct 04 '17 at 22:03
  • @Bergi Until its `[[prototype]]` is replaced. – doubleOrt Oct 04 '17 at 22:04
  • @Taurus A [[prototype]] is never replaced (unless you use `Object.setPrototypeOf`), it's chosen when the object is created and should stay the same afterwards. Again, setting the `.prototype` property does **not** change the [[prototype]] link!!! – Bergi Oct 04 '17 at 22:09
  • @Bergi I know that setting the `.prototype` property does not change the `[[prototype]]` chain, `.prototype` is merely the `[[prototype]]` of instances created from `.prototype.constructor`. So, in both cases, the parent-to-be is technically set as the `[[prototype]]` of the created object (in both `Object.create()` and the Parasitic Inheritance example I cited earlier). – doubleOrt Oct 04 '17 at 22:19
  • @Taurus No! In the parasitic inheritance example, no instances with that prototype are created - it just returns plain objects, despite using `new`. Which makes two different prototypes and different outcomes. – Bergi Oct 04 '17 at 23:45
  • @Bergi See [this](https://jsbin.com/goziqavora/edit?js,output) example to see what I mean. – doubleOrt Oct 06 '17 at 10:29
  • @Taurus That example is missing `Foo`, so it's still unclear. I also don't get what you mean by "*we technically created an object whose [[prototype]] is that of the object we want to be the parent of our current object*". However, "*the parent instance will be used instead of the object created by "new"*" is definitely relevant. – Bergi Oct 06 '17 at 13:27

1 Answers1

3

The most "right" method I know of to do inheritance in Javascript is this:

let SubClass = function() { SuperClass.call(this, arguments); /*Do other stuff here*/ }
SubClass.prototype = Object.create(SuperClass.prototype);

Object.create(o) is about the same as {__proto__: o} will will create another object with o as its prototype.

However since the world has changed we are live in the ES6 realm now, you would rather use the ES6 standard way of doing inheritance:

class SubClass extends SuperClass {
    constructor() { super(...arguments); /*Do other stuff here*/ }
}

These are the most widely used methods today, stick with whatever fits with you.

Hope this helps.

Noctisdark
  • 350
  • 3
  • 17
  • Wasn't "class" and "extends" introduced to welcome newcomers to Javascript? Aren't they discouraged for regular usage, even in ES6? – Even Steven Oct 16 '16 at 06:21
  • 2
    They are not. `class` and `extends` do not introduce a new way of doing inheritance in Javascript. They are syntactical sugar over the `prototype inheritance`. You can read more at this [Link](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes) – Noctisdark Oct 16 '16 at 07:59
  • Thank you! I just did some investigative research of where I encountered this "belief", and it seems I should be careful of taking advice from Eric Elliot. He tends to be a top result on Google, but takes Crockford's work to the extreme. I'm not really sure where to start anymore. – Even Steven Oct 17 '16 at 05:40