JavaScript 原型链主要有以下几种方式来查找和继承属性和方法:
通过将子类的原型对象(prototype)设置为父类的一个实例,从而实现继承。这种方式的优点是简单易懂,但缺点是所有子类实例共享父类的引用属性,无法实现多继承。
function Parent() {
this.name = 'parent';
}
Parent.prototype.getName = function() {
return this.name;
};
function Child() {
this.age = 18;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var child1 = new Child();
console.log(child1.getName()); // 'parent'
在子类构造函数中调用父类构造函数,并将子类实例作为上下文(this)。这种方式的优点是可以避免子类实例共享父类引用属性的问题,但缺点是无法继承父类原型上的方法。
function Parent() {
this.name = 'parent';
}
Parent.prototype.getName = function() {
return this.name;
};
function Child() {
Parent.call(this);
this.age = 18;
}
var child1 = new Child();
console.log(child1.name); // 'parent'
console.log(child1.getName); // undefined
结合原型链继承和构造函数继承的优点,实现属性和方法的继承。缺点是父类构造函数会被调用两次。
function Parent(name) {
this.name = name;
}
Parent.prototype.getName = function() {
return this.name;
};
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var child1 = new Child('parent', 18);
console.log(child1.name); // 'parent'
console.log(child1.getName()); // 'parent'
通过创建一个新对象并将其原型设置为父类实例,实现继承。这种方式的缺点是同样会导致子类实例共享父类引用属性。
function Parent() {
this.name = 'parent';
}
Parent.prototype.getName = function() {
return this.name;
};
function createObject(proto) {
function F() {}
F.prototype = proto;
return new F();
}
var child1 = createObject(Parent.prototype);
child1.name = 'child';
console.log(child1.getName()); // 'child'
在原型式继承的基础上,增加一个函数用于封装继承过程并添加新的方法。这种方式的缺点仍然是子类实例共享父类引用属性。
function Parent() {
this.name = 'parent';
}
Parent.prototype.getName = function() {
return this.name;
};
function createChild() {
var clone = Object.create(Parent.prototype);
clone.age = 18;
return clone;
}
var child1 = createChild();
child1.name = 'child';
console.log(child1.getName()); // 'child'
结合寄生式继承和组合继承的优点,避免了父类构造函数被调用两次的问题。
function Parent(name) {
this.name = name;
}
Parent.prototype.getName = function() {
return this.name;
};
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
var child1 = new Child('parent', 18);
console.log(child1.name); // 'parent'
console.log(child1.getName()); // 'parent'