0

In chapter 6 (Code Reuse Patterns) there is following example:

// the parent constructor
function Parent(name) {
    this.name = name || 'Adam';
}

// adding functionality to the prototype
Parent.prototype.say = function () {
    return this.name;
};

// empty child constructor
function Child(name) {}

// inheritance magic happens here
inherit(Child, Parent);

In section "Classical Pattern #1 — The Default Pattern" the implementation of the inherit() function is:

function inherit(C, P) {
    C.prototype = new P();
}

In the section "Drawbacks When Using Pattern #1" is the following example:

var s = new Child('Seth');
s.say(); // "Adam"

I don't understand the following author's explanation:

This is not what you’d expect. It’s possible for the child to pass parameters to the parent’s constructor, but then you have to do the inheritance every time you need a new child, which is inefficient, because you end up re-creating parent objects over and over.

How is it possible for the child to pass a parameter to the parent's constructor? And how is it possible to change the prototype of an child object after construction if not through the hidden prototype property? Could anyone please give me an example for that, what the author means?

Mat
  • 3
  • 1

3 Answers3

2

you have to do the inheritance every time you need a new child, which is inefficient, because you end up re-creating parent objects over and over.

It's not inefficient, not further objects are created if done properly. Indeed, you will have to do explicit inheritance every time for passing parameters and invoking parent constructors.

function Child(name) {
    Parent.call(this, name); // apply the parent constructor on new instance
                             // to set up instance variables like `name`
}

// inheritance stuff happens here
Child.prototype = Object.create(Parent.prototype);

… which is no magic when you understand how the prototype chain works and what Object.create does.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Exactly thing that I was going to write:) Mat - you could read something from Douglas Crockford, http://javascript.crockford.com/prototypal.html – Entity Black Feb 06 '14 at 17:37
  • @Windkiller With all the sugar that Crockford throws into "classical inheritance" he still does it wrong: http://javascript.crockford.com/inheritance.html#sugar Creating an instance of Parent to set up prototype part of Child is wrong so `this.prototype = new parent();` should be `this.prototype = Object.create(parent.prototype);' Crockford has some nice patterns but what he himself called "classical" he can't seem to get right. – HMR Feb 07 '14 at 02:55
  • @Windkiller He also forgets to re use Parent constructor code by calling `Parent.call(this,args);` in Child wich makes setting Child.prototype to an instance of parent all the more dangerous (http://stackoverflow.com/a/21550855/1641941). More info about what args is in that code here: http://stackoverflow.com/a/16063711/1641941 under "Passing (constructor) arguments" – HMR Feb 07 '14 at 02:58
  • @HMR - Except the fact that Object.create is based on old Crockfords patterns. So of course that he didnt use it, because it didn't exist. Also his patterns are now used as a shim for browsers that doesn't support Object.create. – Entity Black Feb 07 '14 at 13:31
  • @Windkiller: The `Object.create` pattern is based on way older patterns in early OOP languages like Self, using a "clone" function. – Bergi Feb 07 '14 at 13:38
  • @Bergi - Then why is its polyfill identical to Crockoford's pattern?? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create – Entity Black Feb 07 '14 at 13:45
  • Sure, he advocated for having a native function for pure prototypical inheritance in the language, which could only be shimmed with `new` before, but he didn't invent the "clone" pattern. Not sure who first came up with the particular shim implementation. – Bergi Feb 07 '14 at 13:50
  • 1
    @Windkiller Crockford has some good stuff and good presentations but I have yet to see a presentation or blog post where he correctly uses "classical inheritance". For someone who starts with OOP JavaScript and tries to understand constructor functions and prototype he is of no help. The polyfil has been around for years and was also used in closure libraries `goog.inherits` http://bolinfest.com/javascript/inheritance.php (2009) But Crockford still mis informs people in 2011: http://stackoverflow.com/a/21617146/1641941 – HMR Feb 07 '14 at 14:50
  • Ok, can't disagree with that ;) – Entity Black Feb 07 '14 at 15:04
1

The proposed inheritance scheme is rotten.
The right way to inherit, even in the 'simple way' is :

// the parent constructor
function Parent(name) {
    this.name = name || 'Adam';
}

// adding functionality to the prototype
Parent.prototype.say = function () {
    return this.name;
};

// Child constructor
function Child(name) {
      Parent.apply(this, arguments);  // to call with exact same parameters.
     // or  .call(this, /* the parameters you want */ ) ;
}

Child.prototype = Object.create(Parent.prototype); 

Child.prototype.otherMethod = function() { /*...*/} ;

Note that calling new P() instead of doing Object.create(P.prototype) is completely stupid, especially since the constructor might not accept no arguments. In this case, your application might throw an exception just for the inheritance, when Object.create cannot fail...

Forget about the other comments also... Talking about inefficiency for one object creation per class (not per instance) is just irrelevant. (maybe forget about the book ? :-) )

GameAlchemist
  • 18,995
  • 7
  • 36
  • 59
1

As Bergi pointed out you should not create an instance of Parent to set up prototype part of Child.

To deal with constructor parameters or passing parameters to a function chain that is under construction (code you have to maintain and applications that need new features in the future are always under construction) you can use one object to be used when passing arguments.

This is also helpful when you use a mediator/publish subscribe object and never know what function will be called after another is finished.

For an example see here under "Passing (constructor) arguments"

Community
  • 1
  • 1
HMR
  • 37,593
  • 24
  • 91
  • 160