继承发展史
1:传统的继承->原生链
缺点:过多的继承了不用的属性。
2:借用构造函数
缺点:不能基础构造函数的的原型,需要多调用一个构造函数,耗时。
3:共享原型
缺点:不能随便更改自己的原型
4:圣杯模式
前俩种继承模式可以看一下我之前的博客。
3:共享原型
看一下下面代码
Father.prototype.sex="male";
function Father() {
}
function Son() {
}
Son.prototype=Father.prototype;
var son=new Son();
var father=new Father();
我们直接把Son.prototype赋值为Father.prototype,那么Son的原型就是Father的原型了,可以看到son已经有sex属性了。
也就是Father.prototype是Father和Son的原型了。
但是这里有个问题
我们仅仅想改变一下Son的原型但是Father也改变了,这个是肯定不行的。
这就是共享原型的致命缺点。
原因也很简单:因为Son.prototype与Father.prototye已经指向同一个地址了,你改我就跟着改了。
圣杯模式
圣杯模式其实也是利用了刚刚共享原型的思想,但是改变了一个小小的变化,然后就完美了解决了共享原型的缺点。
看如下代码:
Father.prototype.sex="male";
function Father() {
}
function Son() {
}
function inherit (target,origin) {
function F() {};
F.prototype=origin.prototype;
target.prototype=new F();
}
inherit(Son,Father);
var son=new Son();
var father=new Father();
我们封装了一个函数inherit,其实也没啥,看关键咯,我们生成了一个构造函数F(),里面什么都不放,当作中间量,就巧妙的避开了Son.prototype与Father.prototype地址相同,因为Son.prototype等于一个新F()函数,而F()函数什么都没有,其实就是利用的F.prototype.
不过还有俩点需要注意:
1:我们现在访问一下son.constructor属性。
发现它变成Father了,明明是Son构造函数产生的,那么为什么了?
我们知道Son.prototype为F,F.prototype=Father.prototype
那么son.__proto__=new F().__proto__=Father.prototype.原因就在这里。
2:开发中有的时候需要知道Son的原型到底是谁,所以我们需要保存一下它的真正的原型
代码如下:
function inherit (target,origin) {
function F() {};
F.prototype=origin.prototype;
target.prototype=new F();
target.prototype.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.prototype.constructor=target;
target.prototype.uber=origin.prototype;
}
}());
这个就更完美了,利用了闭包的特性,外界是访问不到F()函数的。