JS的圣杯模式是每一位前端开发者都需要掌握的。
但它跟原型链又挂钩,原型链对于刚接触前端的人而言,并不好理解。
我通过解释圣杯模式的代码也能帮你很好的理解原型链
先上圣杯模式的代码
const inherit = (function () {
function F() {};
return (Target,Origin) => {
F.prototype = Origin.prototype;
Target.prototype = new F();
// 这个圣杯模式虽然代码简单,但涉及的原型链知识可不是那么好理解
Target.prototype.constructor = Target; // 这两行代码不是那么好理解为什么要这么做
Target.prototype.uber = Origin;
}
}());
核心代码
先看一下核心代码
const inherit = (function () {
function F() {}; // 只有这几句代码在原型链的情况是怎么样的
return (Target,Origin) => {
F.prototype = Origin.prototype;
Target.prototype = new F();
}
}());
这几句代码就已经可以实现圣杯模式。
那只有这几句代码在原型链的情况是怎么样的
以一个继承栗子来看
function Person(name) {
this.name = name;
}
function Animate(type) {
this.type = type;
}
Animate.prototype.show = function(){
console.log(this.name,this.type);
}
inherit(Person,Animate);
Person.prototype.abc = "abc";
const p = new Person();
原型链的继承关系如下
从原型链的继承结果来看,Person
的实例对象能访问到Animate
的原型是因为它们通过一个中间的对象(F构造函数的实例)进行连接,而F构造函数的原型指向Animate
原型。
并且往Person的原型【prototype
】上添加属性,等于往中间对象f
【F构造函数的实例】加东西,不会影响Animate的原型。
同时以上代码通过立即函数和闭包的形式私有化F
变量。
这就是圣杯模式最核心的理念。
看到这其实圣杯模式也就理解得差不多了
但核心代码还是有不足之处
这也就是最后两行代码的意义
Target.prototype.constructor = Target; // 这两行代码不是那么好理解为什么要这么做
Target.prototype.uber = Origin;
先要知道一点
constructor
是prototype中的一个属性,constructor,它也是一个对象,它指向构造函数本身。
如果没有最后两行代码,按照上面给的栗子是什么情况
先看p的constructor
按正常逻辑,不应该是指向实例化这个对象的构造函数本身吗?
为什么不是Person,而是Animate?
还是要来捋一捋原型链的关系。
Person.prototype是谁
是不是f
那么f
是对象不是原型,就往原型链上找,找到谁了
是不是F的原型 F.prototype
F.prototype指向Animate的原型
那Animate的原型的constructor
指向是不是自己的构造函数Animate
整个过程一捋下来是不是清晰明了。也对原型链有了一定理解呢?
接近尾声了
就是最后两行代码的意义
Target.prototype.constructor = Target;
Target.prototype.uber = Origin;
单独看这两行代码,可能不太清楚
那就放到实际栗子中看。
这个Target是Person
Origin是Animate
上面的代码是不是就是把
Person
的prototype
的constructor
指向他自己的构造方法
然后又将他的超类,可以认为是它的父类的构造方法放到一个uber
属性中方便查找它继承自谁。
另外可能有人发表疑问了?
这样子不会把Animate的原型的constructor
也指向Person了吗?
兄弟这原型链很清晰吧,Person.prototype指向f
,这怎么可能影响到Animate的原型。
好了,如果这篇博客对你有帮助或是有什么错误,欢迎在下方留言。
评论告诉我这篇博客怎么样?谢谢咯~~