1、原型链式继承(类式继承)
function SuperClass() {
this.books = ['css','js','html'];
}
function SubClass(){}
SubClass.prototype = new SuperClass();
var obj1 = new SubClass();
var obj2 = new SubClass();
console.log(obj2.books); //['css','js','html'];
obj1.books.push('设计模式');
console.log(obj2.books) //['css','js','html','设计模式'];
类式继承的缺点:1)由于子类通过其原型prototype对父类实例化,继承了父类。如果父类中的共有属性要是引用类型,就会在子类中被所有实例共用,因此子类的实例更改由父类构造函数中继承来的共有属性就会直接影响到其他子类。2)子类实现的继承是靠其原型prototype对父类的实例化实现的,因此在创建父类的时候,是无法向父类传递参数的,因而在实例化父类的时候也无法对父类构造函数内的属性进行初始化。
2、构造函数继承
function SuperClass(price) {
this.books = ['css','js','html'];
this.price = price;
}
SuperClass.prototype.sayBooks = function(){
console.log(this.price);
}
function SubClass(price){
//此句是构造函数的重点,或者可以SuperClass.apply(this,[price])
SuperClass.call(this,price);
}
var obj1 = new SubClass(50);
var obj2 = new SubClass(60);
console.log(obj2.books); //['css','js','html'];
obj1.books.push('设计模式');//['css','js','html','设计模式'];
console.log(obj2.books) //['css','js','html'];
obj2.sayBooks(); //TypeError
由于call或者apply方法可以改变函数的作用变量,因此在子类中,对superClass调用这个方法就是将子类中的变量在父类中执行一遍,由于父类是给this绑定属性的,因此子类自然就继承了父类的共有属性。
由于这类继承没有涉及原型prototype,这样父类的原型方法自然不会被子类继承,如果想要被继承,就必须要放在构造函数中,这样创建出来的每个实例都会单独拥有一份而不能被公用,违背了代码复制的原则。
3、原型式继承和构造函数组合继承。
function SuperClass(price) {
this.books = ['css','js','html'];
this.price = price;
}
SuperClass.prototype.sayBooks = function(){
console.log(this.price);
}
function SubClass(price){
//此句是构造函数的重点,或者可以SuperClass.apply(this,[price])
SuperClass.call(this,price);
}
//原型继承
SubClass.prototype = new SuperClass();
var obj1 = new SubClass(50);
var obj2 = new SubClass(60);
console.log(obj2.books); //['css','js','html'];
obj1.books.push('设计模式');//['css','js','html','设计模式'];
console.log(obj2.books) //['css','js','html'];
obj2.sayBooks(); //TypeError
不足: 组合继承存在不足,就是会调用两次超类构造函数。
4、寄生式继承
寄生式继承是与原型式继承相关的一种思路
function object(o) {
function F() {};
F.prototype = o;
return new F();
}
function createAnother(original) {
var clone = object(original);
clone.sayHi = function(){
alert('hi');
}
return clone;
}
// 创建一个person
const person = {
name: 'koga',
friends: ['xiaoming', 'xiaohong']
}
const anotherPerson = createAnother(person);
anotherPerson.sayHi(); // 'hi'
5、寄生组合继承
寄生组合式继承: 通过构造函数来继承属性,通过原型链的混成形式来继承方法。基本思路是: 不必为了指定子类型的原型而调用超类型的构造函数,需要的就是超类型原型的一个副本而已。本质上就是使用寄生式继承类继承超类型的原型,再将结果指定给子类型的原型。
function object(o){
function F(){}
F.prototype = o;
return new F();
}
function inheritProperty(subType, superType) {
var prototype = object(superType.prototype); // 创建 对象
prototype.constructor = subType; // 增强对象
subType.prototype = prototype; // 指定对象
}
function SuperType(name) {
this.name = name;
this.friends = ['xiaoming', 'xiaohong']
}
SuperType.prototype.sayHi = function(){
alert('Hi');
}
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}
inheritProperty(SubType, SuperType);
SubType.prototype.sayAge = function() {
alert(this,age)
}