1. 原型链继承
JavaScript中,每个函数都有一个prototype
属性,这个属性是一个指向原型对象的指针。原型对象默认包含一个名为constructor
的属性,指向原函数。当我们使用构造函数创建实例时,每个实例内部都有一个指向其构造函数原型对象的指针__proto__
(在ES6中,通过Object.getPrototypeOf()
方法访问)。如果原型对象中包含一个指向另一个类型的原型对象的指针,相应地,就形成了一个原型链。
function Parent() { this.name = 'parent';
} Parent.prototype.sayName = function() { console.log(this.name);
}; function Child() { this.age = 10;
} // Child继承Parent
Child.prototype = new Parent();
Child.prototype.constructor = Child; var child = new Child();
child.sayName(); // 'parent'
2. 借用构造函数继承(伪造对象或经典继承)
在子类的构造函数中,通过调用父类的构造函数,并使用call()
或apply()
方法,可以将父类的属性“借用”给子类实例。
function Parent(name) { this.name = name;
} function Child(name, age) { Parent.call(this, name); // 继承Parent的name属性 this.age = age;
} var child = new Child('child', 5);
console.log(child.name); // 'child'
3. 组合继承(原型链+借用构造函数继承)
组合继承是原型链继承和借用构造函数继承的组合,它结合了两种继承方式的优点,既可以通过原型链继承父类原型上的属性和方法,又可以通过构造函数继承父类的实例属性。
function Parent(name) { this.name = name;
} Parent.prototype.sayName = function() { console.log(this.name);
}; function Child(name, age) { Parent.call(this, name); // 继承属性 this.age = age;
} Child.prototype = new Parent(); // 继承方法
Child.prototype.constructor = Child; Child.prototype.sayAge = function() { console.log(this.age);
}; var child = new Child('child', 5);
child.sayName(); // 'child'
child.sayAge(); // 5
4. 原型式继承
原型式继承是借助原型可以基于已有的对象创建新对象,同时实现原型链继承。
function object(o) { function F() {} F.prototype = o; return new F();
} var person = { name: 'John', friends: ['Sheldon', 'Leonard', 'Howard']
}; var anotherPerson = object(person);
anotherPerson.name = 'Jane';
anotherPerson.friends.push('Penny'); console.log(person.friends); // ['Sheldon', 'Leonard', 'Howard', 'Penny']
5. 寄生式继承
寄生式继承是创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回对象。
function createAnother(original) { var clone = object(original); // 通过原型式继承获得原始对象的浅拷贝 clone.sayHi = function() { // 增强对象 console.log('hi'); }; return clone; // 返回增强后的对象
} var person = { name: 'John'
}; var anotherPerson = createAnother(person);
anotherPerson.sayHi(); // 'hi'