使用JavaScript的Prototypal继承链

时间:2013-12-22 21:10:36

标签: javascript inheritance

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}
Person.prototype.talk = function () {
    return this.firstName + " " + this.lastName;
}
//creating a Person object for extension
var manager = new Person('jon', 'doe');
console.log(manager.talk());
//Manager prototype..but doesn't inherit Person methods 
function Manager(firstName, lastName, accessCode) {
    //shared properties
    this.firstName = firstName;
    this.lastName = lastName;

    this.accesscode = accessCode;
}
function personChecker(person) {
    var returnCode = 0;
    if (person instanceof Person) {
        returnCode = 1;
    }
    else if (person instanceof Manager) {
        returnCode = 2;
    }
    return returnCode;
}
console.log(personChecker(manager));

是否可以共享原型并拥有不同的构造函数?我想让Manager继承Person中的所有东西(然后扩展它)并在原型上有一个函数开关,并根据传递给personChecker函数的参数做一些不同的事情

3 个答案:

答案 0 :(得分:2)

支持此继承的典型方法:

// create a blank function to pass the prototype
var blank = function() {};

// assign the prototype to inherit to the blank constructor
blank.prototype = Person.prototype;

// pass an instance of the prototype as the Manager prototype
Manager.prototype = new blank();

var person = new Person('John', 'Doe');
var manager = new Manager('Greg', 'Smith', 'access1234');

manager.talk(); // Greg Smith
person.talk(); // John Doe

这是一个小提琴:http://jsfiddle.net/XF28r/

请注意,经理也是一个人,因此您需要切换支票。

function personChecker(person) {
    var returnCode = 0;
    if (person instanceof Manager) {
        returnCode = 2;
    } else if (person instanceof Person) {
        returnCode = 1;
    }
    return returnCode;
}

虽然注意我会把它放在一个辅助方法中:

function extend(parent, child) {

  var blank = function() {};
  blank.prototype = parent.prototype;
  child.prototype = new blank();
}

那么你可以简单地使用它:

extend(Person, Manager);

正如Bergi在评论中提到的,这也可以简化为:

function extend(parent, child) {
  child.prototype = Object.create(parent.prototype);
}

(IE 9向上工作)

答案 1 :(得分:2)

在JavaScript中,继承通常是这样完成的:

Manager.prototype = Object.create(Person.prototype);

Object.create创建一个新对象,其对象作为其原型链中的第一个参数传递。

如果您需要支持没有Object.create的旧浏览器,您可以改为“原型舞”:

function F(){}
F.prototype = Person.prototype;
Manager.prototype = new F();

在任何情况下,避免代码调用构造函数来获取这样的对象(Manager.prototype = new Person()),这是一个众所周知的反模式,并且一旦构造函数依赖于它的任何参数就会中断(并且它会导致其他更微妙的问题。)

答案 2 :(得分:1)

使用以下内容:

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}
Person.prototype.talk = function () {
    return this.firstName + " " + this.lastName;
}

function Manager(firstName, lastName, accessCode) {
    //shared properties
    this.firstName = firstName;
    this.lastName = lastName;

    this.accesscode = accessCode;
}
Manager.prototype = new Person('jon', 'doe');

function personChecker(person) {
    var returnCode = 0;
    if (person instanceof Manager) {
        returnCode = 2;
    }
    else if (person instanceof Person) {
        returnCode = 1;
    }
    return returnCode;
}

请注意,我更改了条件的顺序,因为Manager的实例也是Person的实例:

var per = new Person('A', 'B');
per.talk();              // 'A B'
per instanceof Person;   // true
per instanceof Manager;  // false
personChecker(per);      // 1

var man = new Manager('A', 'B');
man.talk();              // 'A B'
man instanceof Person;   // true !!!!
man instanceof Manager;  // true !!!!
personChecker(man);      // 2

如果你想以好方式去做,而不是

Manager.prototype = new Person('jon', 'doe');

使用

Manager.prototype = Object.create(Person.prototype, {constructor: {value: Manager}});

但它不适用于旧浏览器。