在js中无论是创建对象,实现继承都需要用到原型相关的知识,究竟什么是原型,下面会进行详细的解释:
相信大家都听说过万物皆对象,对象皆为空这句话,可能学习过一些其他如java,php等语言的小伙伴理解的比较深刻。那后边一句对象皆为空是什么意思哪?待会再聊~
- 首先打开编辑器新建一个html文件,然后在script标签内输入以下代码,可以看出当前创建的是一个对象,然后在控制台查看
<script>
let obj = new Object();
console.dir(obj);
</script>
控制台会显示如下的内容:
对象下边第一个是__proto__,现在不理解没关系,我们再来创建一个构造函数
function test(){}
console.dir(test);
这时候浏览器上会出现如下内容,当然如果没有人在旁边一点一点的解释,可能自己理解起来很难,下边直接说结论:
一般的obj(对象)的原型是__proto__函数的原型是prototype(包括构造函数哦)但是要强调的是这里的__proto__不是一个标准属性(就行一个人的外号一样)你可以通过这个名字去认识它,但是它并不是一个标准的名字,它的标准名字是[[proto]],原型是一个对象,其他对象可以通过原型实现属性的继承除了prototype,__proto__是每个对象都有的属性。
如下图:
重点来啦,要把下边的一个式子当作公式去记哦,记住你就明白了原型:
对于一般情况
proto = cunstructor.prototype
原型的指向
首先要先明确一句话
__proto__的指向取决于对象创建时的实现方式
原型对象的指向分为三种
1.字面量方式(符合上边公式)
2.构造函数方式(符合上边方式)
3.
var c = {};
var d = Object.creat(c);
console.log(d.__proto__) //===c
console.log(d.__proto__===d.cunstrutor.prototype)// ===false
直接说结论:
以上边这种方式创建的原型等于创建它的原对象
原型链
var A = function(){}
var b= new A() //{}
console.log(b.__proto__)//A.prototype
console.log(b.__proto__.___proto__)//{}
cosole.log(b.__proto__.___proto__.__proto__)//null
运行结果如下图所示:
而一直这样求它的原型构成的一条链就是原型链,“顶级原型”是一个null,这就是“对象皆为空”
总结:由于__proto__是任何对象都有的属性,而js万物皆对象,所以会形成一条由__proto__直接连接起来的原型链(递归访问)必定最终到头,而且值为空null。
当js引擎查找对象时,先查找本身是否有该属性,如果不存在,会在原型链上查找,但不会查找自身的prototype。