-
原型链继承
function Person(name, age) {// 父 this.name = name; this.age = age; } function Student() { // 子 } Student.prototype = new Person();
每个构造函数(Person)都有原型对象(prototype),指向Object的实例上的proto属性,Object.Prototype为null
子类构造函数的prototype指向父类的实例,而父类构造函数的prototype指向Object的实例,通过这种关系,形成了原型链。
确定原型和实例之间的关系
a. instanceof操作符
b. isPrototypeOf()
Object.prototype.isPrototypeOf(instance) true
缺点:父子之间共享引用类型的值,不能给父类构造函数传递参数。 -
借用构造函数
在子类的构造函数中调用父类的构造函数,可以避免原型链继承方式中的引用类型值共享的问题,以及不方便向父类构造函数中传递参数的问题(因为可能会影响父类的实例)
通过call或者apply实现function Person(name, age) {// 父 this.name = name; this.age = age; } function Student(name, age, score) { // 子 Person.call(this, name, age) this.score = score }
缺点:在构造函数中定义方法不能实现方法复用
-
组合继承
原型链继承(继承原型上的属性和方法)+借用构造函数(继承实例上的属性)function Person(name, age) {// 父 this.name = name; this.age = age; } function Student(name, age, score) { // 子 Person.call(this, name, age) this.score = score } Student.prototype = new Person(); Student.prototype.constructor = Student; Student.prototype.sayScore = function() { alert(this.score) }
缺点:会调用两次父类的构造函数
-
原型式继承
由道格拉斯.克罗克福德提出,基本思想:借助原型可以基于已有的对象创建新对象,同时也不用创建自定义类型。function object(o) { function F() {} F.prototype = o; return F() }
ECMAScript5新增Object.create()规范了原型式继承,
Object.create(proto[,propertiesObject])
,使用现有的对象来提供新创建的对象的proto(来自MDN),返回继承了proto的对象。第二个参数与Object.defineProperties()的第二个参数相同。缺点:同原型链继承一样,引用类型的值会共享
-
寄生式继承
同样由道格拉斯.克罗克福德提出,思路与原型式继承紧密相关:创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回对象。function createAnother(original) { // 也可以用其他方法来创建clone,比如Object.create() var clone = object(original); clone.sayName = function() { alert('hi') } return clone }
缺点:不能函数复用,与借用构造函数类似
-
寄生组合式继承(理想的调用方式)
通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。
不用调用两次父类的构造函数
function inheritPrototype(subType, superType) {
var prototype = Object(superType.prototype); // 创建对象
prototype.constructor = subType; // 增强对象
subType.prototype = prototype; // 指定对象
}
function Person() {}
function Student() {
Person.call(this)
}
inheritPrototype(Student, Person);
网友评论