创建javascript原型继承链的不同方式

时间:2016-08-17 04:02:01

标签: javascript prototype-chain

function Parent(parentName){
  this.name = parentName;
}

Parent.prototype.printName = function(){
  console.log(this.name);
}

var p = new Parent("Parent");
console.log(p);

function Child(parentName, childName){
  Parent.call(this, parentName);
  this.name = childName; 
}

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

var c = new Child("Parent","Child");
console.log(c);

有人可以告诉我上述陈述1和1之间的区别吗? 2.无论哪种方式,子对象都能够调用c.printName();

2 个答案:

答案 0 :(得分:2)

2之间有很大的不同 原型中最令人困惑的部分之一就是你有原型和 proto 这一事实。

Protoype是函数对象的一个​​特殊属性,每当你使用new关键字调用构造函数时,实例proto都将是构造函数原型。

Object.create是一种允许您创建新对象并将其指定为 proto 的方法。

因此,当通过方法1分配您的Child类原型时,您将为您的孩子类提供一个全新的原型对象,它将通过 proto 链接继承原型继承,父母的方法。 这是更好的选择,因为您可以在不影响父原型的情况下对子原型进行修改,因为它是一个不同的对象。

另一方面,选项2 你为两个类分配了相同的原型,它们都引用同一个对象,因此对子原型的改变会影响父原型,这通常不是理想的情况,也不是一个好的做法。

方法1的示例:

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



function Parent(){
  this.x = 0;
}

Parent.prototype.add = function(n){
  this.x+= n;
  return this.x;
};

var parentInstance  = new Parent();
console.log('new Parent instance');
console.log('parentInstance.add(1): ' + parentInstance.add(1));

console.log('now letss add child, which will always add 10, to the add value');

function Child(){
    Parent.call(this);
}
console.log('setting child prototype via method 1');
console.log('Child.prototype = Object.create(Parent.prototype);');
Child.prototype = Object.create(Parent.prototype);
console.log('overriding child add function, to always add 10 to given n');
Child.prototype.add = function(n){
  this.x+= n + 10;
  return this.x;
}
var childInstance  = new Child();
console.log('new child instance');
console.log('childInstance.add(1): ' + childInstance.add(1));
console.log('yay child is working');
console.log('now lets add again to our parent instance');
console.log('parentInstance.add(1): ' + parentInstance.add(1));
console.log('yay parent is still working');




方法2的示例:

Child.prototype = Parent.prototype;



function Parent(){
  this.x = 0;
}

Parent.prototype.add = function(n){
  this.x+= n;
  return this.x;
};

var parentInstance  = new Parent();
console.log('new Parent instance');
console.log('parentInstance.add(1): ' + parentInstance.add(1));

console.log('now letss add child, which will always add 10, to the add value');

function Child(){
    Parent.call(this);
}
console.log('setting child prototype via method 2');
console.log('Child.prototype = Parent.prototype;');
Child.prototype = Parent.prototype;
console.log('overriding child add function, to always add 10 to given n');
Child.prototype.add = function(n){
  this.x+= n + 10;
  return this.x;
}
var childInstance  = new Child();
console.log('new child instance');
console.log('childInstance.add(1): ' + childInstance.add(1));
console.log('yay child is working');
console.log('now lets add again to our parent instance');
console.log('parentInstance.add(1): ' + parentInstance.add(1));
console.log('oops we broke parent');




答案 1 :(得分:2)

1和2之间的差异是

第一个是使用指定的原型对象和属性创建一个新对象,而不是与父

共享

Object.create(Parent.prototype)做的是它返回一个新对象和父对象的原型,但是第二个你只是将子原型引用(指向)父对象原型,所以如果你给子原型添加一个属性,请说

Child.prototype.age = function(){
  console.log("parent can access this method");
}
p.age();

父级可以访问此方法被打印,对于经典继承,您可能希望使用第一种方法但是第二种方法有一些用例

只是为了扩展这篇文章,在我看来,继承的最好方法是做

// parent object
var Parent = {
    firstname: "john",
    getFirstName  : function () {
        console.log(this.firstname);
    }
};


// create a child object with all the properties and methods of Parent
var child = Object.create(Parent);
// add or modify child properties
child.lastname = "doe";
child.getLastName = function () {
    console.log(this.lastname);
};


// create instances of child object
baby1 = Object.create(child);
baby1.firstname = "alice";
baby1.getFirstName();
baby1.getLastName();

// to see the prototype chain 
console.log("baby1 properties: ", baby1);
console.log("baby1 parent properties: ", baby1.__proto__);
console.log("baby1 grandpa properties: ", baby1.__proto__.__proto__);

非常简单,不使用电话或手动原型管理