4

Suppose I have two constructor function:

var Person = function(xx,xx,xxx,xxxxxxx) {
  //Person initialization
}

var Man = function(xx,xx,xxx,xxx) {
  //Man initialization
}

And I want Man extends from Person.

The following is what I thought:

Given a created Man object:

var m=new Man("xx",....);

1) when a property of m is accessed,it will search it in Man.prototype.

2) If not find, It should find it in Man.prototype.__prop__.

So what I have do is make the Man.prototype.__prop__ linked to Person.prototype.

I know this is the common way:

function inherit(superClass) {
    function F() {}
    F.prototype = superClass.prototype;
    return new F;
}
Man.prototype=inherit(Person);

But when I try this:

Man.prototype.prototype=Person.prototype.

Why it does not work?

hguser
  • 35,079
  • 54
  • 159
  • 293

3 Answers3

6

It sounds like you actually want to link instances of Man to an instance of Person that retains any properties added in its constructor, in which case you might really want something like this:

function Person(a, b) {
    this.a = a;
    this.b = b;
}

function Man() {}
Man.prototype = new Person("val1", "val2");

var m = new Man();
console.log(m.a);

...which prints val1.

Additional Ramblings

The purpose of inherit is to create an object from a function whose prototype is that of the given super class (without explicitly using new), which is exactly what it does. Therefore, the following prints string:

function Person() {}
Person.prototype.test = "string";

function Man() {}

function inherit(superClass) {
    function F() {}
    F.prototype = superClass.prototype;
    return new F;
}

var t = inherit(Person);
console.log(t.test);

But you generally want to assign the returned object to another function's prototype:

Man.prototype = inherit(Person);

var m = new Man();
console.log(m.test);

...so that m.test also prints string, which means that objects created using Man are linked to Person's prototype).

Note that Man.prototype.prototype is undefined and -- this is the important part -- also meaningless. Functions have prototypes. Other objects (such as Man.prototype) do not. The prototype property is not magical in any other context. Assigning a value to a random object's prototype property doesn't do anything special. It's just another property.

Note also that the thing we returned from inherit is linked to Person by way of its prototype and has no access to any properties added to instances of Person.

Community
  • 1
  • 1
Wayne
  • 59,728
  • 15
  • 131
  • 126
  • I know this is old, but don't you think that the *really relevant* part of the answer is just the paragraph stating "... The prototype property is not magical in any other context..."? BTW When one inspects the resultant structure of `m`, it really *seems* like nested `prototype` properties (which it actually is, but managed only internally by JS engines, for a reason). So it seems logical to try to set the nested `prototype` directly (as opposed to wrapping the ancestor's `prototype` into an object and overwriting the whole descendant's `prototype` object) as stated in the OP, or doesn't it? – Petr Bodnár Sep 14 '18 at 18:19
3

How I do it (in regards to your example):

var Person = function () {
}

// Define "Person" methods

var Man = function () {
}

Man.prototype = new Person();

// Define "Man" methods

UPDATE

Regarding constructors with parameters: just found this SO question that can really help you figure it out (second answer, first part): JavaScript inheritance: when constructor has arguments.

Community
  • 1
  • 1
volpav
  • 5,090
  • 19
  • 27
0

There are quite a few generic methods to do that. I will provide three of them:

1.) Using Function object as a constructor and as a prototype object for inherited new objects. The implementation should look like as the following:

var person = {
    toString : function() {
        return this.firstName + ' ' + this.lastName;
    }
}


function extend(constructor, obj) {
    var newObj = Object.create(constructor);
    for (var prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            newObj[prop] = obj[prop];
        }
    }
    return newObj;
}

var man = extend(person, 
    {
        sex: "male", 
        age: "22"
    });

var name = extend(man, 
    {
        firstName: "Simo",
        lastName: "Endre"
    });

name.man;
name.toString();

2.) In this case we'll use the Function object as the constructor for simulating the classical inheritance in a language like C# or Java. The prototype property of an object will be used in the role of a constructor and the the newly created object will inherit all the properties from the object prototype root. In this case the object's prototype has only one kind of augmentation role, the effective implementation is done in the function method.

var Person = function(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

Person.prototype.toString = function() {
    return this.firstName + ' ' + this.lastName;
}

function inherit(func) {
    // passing function arguments into an array except the first one which is the function object itself
    var args = Array.prototype.slice.call(arguments, 1);

    // invoke the constructor passing the new Object and the rest of the arguments
    var obj = Object.create(func.prototype);
    func.apply(obj, args);        

    //return the new object
    return obj;   
}

var man = inherit(Person, "Simo", "Endre");
man.toString();

3.) The well known inheritance model:

function extend(o) {
  function F() {}

  // We'll set the newly created function prototype property to the object. 
  //This act as a constructor.
  F.prototype = o;

  // Using the `new` operator we'll get a new object whose prototype is o.
  return new F();
};
Endre Simo
  • 11,330
  • 2
  • 40
  • 49