继承发展史
原型链(弃用)
缺点:过多的继承了没用的属性
Grand.prototype.Lastname = 'Li';
function Grand (){
}
var grand = new Grand();
Father.prototype = grand;
function Father(){
this.name = 'xiaoming';
}
var father = new Father();
Son.prototype = father;
function Son(){
}
var son = new Son();
son 只想继承 father的 属性,但是从头到尾都继承下来了
借用构造函数
即 用 call 或 apply 借用别的构造函数实现自己的需求,如
function Person (name,age){
this.name = name;
this.age = age;
}
function Student (name,age,sex,grade){
Person.call(this,name,age);
this.sex = sex;
this.grade = grade;
}
var student = new Student('zhang',21,'male',3);
缺点:
1、不能继承借用构造函数的原型,
2、每次构造函数都要多走一个函数
每构造一个 对象,就需要执行两个方法 Student 和 Person,增加了函数调用,浪费效率
共享原型
Father.prototype.Lastname = 'zhang'
function Father(){
}
var father = new Father();
function Son(){
}
Son.prototype = Father.prototype;
var son = new Son();
//让一个原型给两个方法(多个也行)
将上面的继承方式,封装成一个方法,如下
Father.prototype.Lastname = 'zhang'
function Father(){
}
function Son(){
}
function inherit(Target,Origin){
Target.prototype = Origin.prototype;
}
inherit(Son,Father);
Son.prototype.sex = 'male';
var father = new Father();
var son = new Son();
当 Son 想多增加一个属性方便后续构造对象时,如 sex属性,Son 和 Father 共用一个原型,在改动的同时,把 father原型也给改变了
缺点:不能随便改动自己的原型
Son 既想 继承 Father.prototype 的属性,又想单独实现自己的一些独特需求而不影响到 Father构造出的对象,
怎么办? 圣杯模式
圣杯模式
Father.prototype.Lastname = 'zhang'
function Father(){
}
function Son(){
}
//用立即执行函数
var inherit = (function(){
var F = function() {}; //作为中间传递
return function(Target,Origin){
F.prototype = Origin.prototype;
Target.prototype = new F();
//Target.prototype.constructor = Target;
};
}());
inherit(Son,Father);
Son.prototype.sex = 'male';
var father = new Father();
var son = new Son();
这样,修改Son 自身的属性,就不会影响到 Father 的属性了
但是,任何一个对象都有一个属性 constructor 存放着构建这个对象的构造函数,也就是说 son.constructor 值应该是是 function Son(){},但是
显然这个 constructor是继承原型链来的
son.proto ——> new F() (F构造出的一个对象) new F().proto ——>Father (){}
所以需要将 Target.constructor 归位
Target.prototype.constructor = Target;
圣杯模式
//用立即执行函数
var inherit = (function(){
var F = function() {}; //作为中间传递
return function(Target,Origin){
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constructor = Target;
};
}());