起因:当我们需要让多个构造函数公用一个原型,那么它可以这样
Father.prototype.name = '123';
function Father(){}
function Son(){}
Son.prototype = Father.prototype;
var father = new Father();
var son = new Son();
father.name; //'123'
son.name; // '123'检查:主要功能基本实现,现在两个构造函数公用一个原型,Son 和 Father 公用一个 prototype,但现在有一个问题,如果我们希望给 Son 增加一个私有的原型上的属性,
我们来试一下
Father.prototype.name = '123';
function Father(){}
function Son(){}
Son.prototype = Father.prototype;
// 给 Son 添加私有属性
Son.prototype.age = 20;
var father = new Father();
var son = new Son();
son.age; //20
father.age; //20再检查:好了,我们已经给 Son 的原型添加了一个 age 属性,但我们发现它并不是私有的,我们通过 father 也能访问这个属性,原因很简单,Son 和 Father 公用的是同一个原型,Son 操作这个原型会影响到 Father 反之亦然,那么我们应该怎么办?
Father.prototype.name = '123';
function Father(){}
function Son(){}
//新建一个构造函数作为中间层
function F(){}
F.prototype = Father.prototype;
Son.prototype = new F();
Son.prototype.age = 20;
var son = new Son();
var father = new Father();
son.name; //'123'
father.name; //'123'
son.age; //20
father.age; //undefined再再检查:嗯,现在我们已经可以给 Son 添加属于自己的原型属性而不会影响到其他人了,很私密,但好像还有点小问题,构造函数有个属性叫 constructor ,它的功能是会指向创造自己的构造函数,我们来检查一下 son 的 constructor 指向哪里
son.constuctor; // Father(){}???,检查一下,额(⊙o⊙)…,我们用构造函数 F 创造了一个对象用来充当 Son 的原型,但对象的没有 constructor 属性的,所以它会沿着原型链向上查找,找到了 Father.prototype ,它的 constuctor 指向的就是 Father();所以打印的就是 Father()
找到问题就简单多了,我们直接把 Son 的 constructor 变成 Son() 就行了,还有我们有时候也会需要知道是谁充当了共享原型,我们可以给它加上一个 uber 属性专门用来记录,最好封装成一个方法以便我们以后使用
function inherit( Target , Origin ){
// 中间层
function F(){}
//共享原型
F.portotype = Origin.prototype;
Target.prototype = new F();
//修改 constructor
Target.constructor = Target;
//记录共享原型
Target.prototype.uber = Origin.prototype;
}下面再分享一下雅虎插件库里大佬的写法
var inherit = (function(){
var F = function(){};
return function( Target , Origin ){
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.constructor = Target;
Target.prototype.uber = Origin.prototype;
}
}());上面的这种写法,我们称之为圣杯模式