什么是__proto__和prototype
先放张经典的图,或许在学习原型的路上你已经无数次看见这张图了,还是看不懂没有关系,先放这,看完此博客决定自己又行了就回来看这图
js实现继承的方式是原型链
原型链的定义:
Javascript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
比如
let arr = [3,2,1] arr = arr.reverse() console.log(arr)// [1,2,3]
我们没有在arr里定义过一个reverse函数,却能够调用,这一定是因为arr从构造函数那继承来的这一函数 以上面代码为例,原型链的定义所描述的就是: arr调用reverse方法,而没有在arr里找到,于是就沿着一条路径找,一层层的找 最终在Array的prototype里找到,然后调用
而_proto_和prototype都是实现原型链的工具。所以我们从寻找的过程去理解_proto_和prototype
声明一个Parent 类,然后实例化一个child,打印一下
class Parent { constructor (name) { this.name = name; } print () { console.log(this.name); } } let child = new Parent(小明); console.log(child.__proto__); console.log(Parent.prototype);
打印结果:
我们发现,child.proto 与 Parent.prototype这俩玩意一模一样:
child.__proto__ === Parent.prototype
而child执行print函数的过程则是:
1、child对象里没有print函数,于是便在其原型上寻找:child.__ proto __ --> Parent.prototype 2、于是便进入Parent.prototype中寻找print函数,有print函数,调用成功
所以我们可以得到这样一个结论:
1、__ proto__是一个访问器,相当于一个索引,用于找到构造函数的prototype 2、prototype是一个构造器,里面包含了构造函数里的各种属性,方法
例子:
function Person(name) { this.name = name } var p2 = new Person(king); console.log(p2.__proto__) //Person.prototype console.log(p2.__proto__.__proto__) //Object.prototype console.log(p2.__proto__.__proto__.__proto__) // null console.log(p2.__proto__.__proto__.__proto__.__proto__)//null后面没有了,报错 console.log(p2.constructor)//Person console.log(p2.prototype)//undefined p2是实例,没有prototype属性 console.log(Person.constructor)//Function 一个空函数 console.log(Person.prototype)//打印出Person.prototype这个对象里所有的方法和属性 console.log(Person.prototype.constructor)//Person console.log(Person.prototype.__proto__)// Object.prototype console.log(Person.__proto__) //Function.prototype console.log(Function.prototype.__proto__)//Object.prototype console.log(Function.__proto__)//Function.prototype console.log(Object.__proto__)//Function.prototype console.log(Object.prototype.__proto__)//null