In JavaScript, how do I inherit from a parent clas

2019-08-04 11:03发布

问题:

For Example:

function Person() {
    //person properties
    this.name = "my name";
}

Person.prototype = {
    //person methods
    sayHello: function() {
        console.log("Hello, I am a person.");
    }

    sayGoodbye: function() {
        console.log("Goodbye");
    }
}

function Student() {
    //student specific properties
    this.studentId = 0;
}

Student.prototype = {
    //I need Student to inherit from Person
    //i.e. the equivalent of
    //Student.prototype = new Person();
    //Student.prototype.constructor = Person;

    //student specific methods
    //override sayHello
    sayHello: function() {
        console.log("Hello, I am a student.");
    }
}

I know I can achieve this using:

function Student() {
    this.studentId = 0;
}

Student.prototype = new Person();
Student.prototype.constructor = Person;
Student.prototype.sayHello = function () {
    console.log("Hello, I am a student.");
}

But I'd like to continue to use style from the first example and have all my class methods defined in a single ".prototype" block if possible.

回答1:

Take a look at the following answer on StackOverflow: https://stackoverflow.com/a/17893663/783743

This answer introduces the concept of prototype-class isomorphism. To put it simply a prototype object can be used to model a class. The following code is taken from the above answer:

function CLASS(prototype) {
    var constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
}

Using the above method we can implement Person as follows:

var Person = CLASS({
    constructor: function () {
        this.name = "my name";
    },
    sayHello: function () {
        console.log("Hello, I am a person.");
    },
    sayGoodbye: function () {
        console.log("Goodbye");
    }
});

Inheritance however requires some additional work. So let's modify the CLASS function a little:

function CLASS(prototype, base) {
    switch (typeof base) {
    case "function": base = base.prototype;
    case "object": prototype = Object.create(base, descriptorOf(prototype));
    }

    var constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
}

We also need to define the descriptorOf function for CLASS to work:

function descriptorOf(object) {
    return Object.keys(object).reduce(function (descriptor, key) {
        descriptor[key] = Object.getOwnPropertyDescriptor(object, key);
        return descriptor;
    }, {});
}

Now we can create Student as follows:

var Student = CLASS({
    constructor: function () {
        this.studentId = 0;
    },
    sayHello: function () {
        console.log("Hello, I am a student.");
    }
}, Person);

See the demo for yourself: http://jsfiddle.net/CaDu2/

If you need any help understanding the code then feel free to contact me.