JavaScript继承发展史
01 原型链(传统模式)
若不太了解 原型链 请参考 原型和原型链的定义和使用.
代码解读
//实例
Father.prototype.lastName = 'wang';
function Father() {
this.name = "dad";
}
var father = new Father();
Son.prototype = father;
function Son() {}
var son = new Son();
优点:父类的方法和属性得到了复用,并且修改属性是不会影响到父类们的。
缺点:过多的继承了没用的属性。
02 借用构造函数
借用构造函数的思想是在子类构造函数的内部调用父类构造函数,借助apply()和call()方法来改变对象的执行上下文。
代码解读
//实例
function Person(name, age) {
this.name = name;
this.age = age;
}
function Student(name, age, grade) {
Person.call(this, name, age);
this.grade = grade;
}
var stu = new Student();
优点:解决原型中包含引用类型值所带来的问题,还可以传递参数。并且子类的每个实例都有自己的属性,不会相互影响。
缺点:不能继承借用构造函数的原型,每次构造函数都要多走一个函数。
03 共享原型
采用
Son.prototype = Father.prototype;
的方式,让son和father的原型都指向同一个空间,即不管改变两者之中的哪一个,另一个也会跟着改变。
代码解读
Father.prototype.lastName = 'wang'
function Father() {}
function Son() {}
Son.prototype = Father.prototype;
// son和father的原型都指向同一个空间,即不管改变两者之中的哪一个,另一个也会跟着改变
//实例如下:
var son = new Son();
var father = new Father();
优点:用法简单。
缺点:不能随便改动自己的原型。
04 圣杯模式(important!)
在共享原型的基础上进行改进,封装一个inherit 函数,并在其中定义一个函数F用来充当中间层的函数之后让F和父类的原型指向同一地址,再让子类的原型指向这个F的对象来实现了继承。(由于有中间层F的存在,因此父类的原型自始至终都没有受到影响)
代码解读
圣杯模式写法1:
function inherit(target, origin) {
function F() {};
F.prototype = origin.prototype;
target.prototype = new F();
target.prototype.constructor = target;
// 让子类的constructor重新指向自己,若不修改则会发现constructor指向的是父类的构造函数
target.prototype.uber = origin.prototype;
// “uber”即超类,超级父级(这个属性可以查询究竟继承的谁)
// “uber”是某些人在模拟class时用来表示super的(因为super是关键字所以不能直接用)。
}
//实例如下:
Father.prototype.lastName = 'wang'
function Father() {}
function Son() {}
inherit(Son, Father);
var son = new Son();
var father = new Father();
圣杯模式写法2:
var inherit = (function () {
// 采用闭包方式实现封装和属性私有化
var F = function () { };
return function (Target, Origin) {
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constructor = Target;
// 让子类的constructor重新指向自己,若不修改则会发现constructor指向的是父类的构造函数
Target.prototype.uber = Origin.prototype;
// “uber”即超类,超级父级(这个属性可以查询究竟继承的谁)
// “uber”是某些人在模拟class时用来表示super的(因为super是关键字所以不能直接用)。
}
}());
//实例如下:
Father.prototype.lastName = 'wang'
function Father() {}
function Son() {}
inherit(Son, Father);
var son = new Son();
var father = new Father();
优点:中间生成了一个对象,起到了隔离的作用。既可以有父辈的属性和方法,改变自己的时候,也不会影响父辈的属性。
个人笔记,欢迎大家交流探讨!