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?

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

9 Comments

Exactly thing that I was going to write:) Mat - you could read something from Douglas Crockford, javascript.crockford.com/prototypal.html
@Windkiller With all the sugar that Crockford throws into "classical inheritance" he still does it wrong: 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.
@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 (stackoverflow.com/a/21550855/1641941). More info about what args is in that code here: stackoverflow.com/a/16063711/1641941 under "Passing (constructor) arguments"
@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.
@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 bolinfest.com/javascript/inheritance.php (2009) But Crockford still mis informs people in 2011: stackoverflow.com/a/21617146/1641941
|
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 ? :-) )

Comments

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"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.