prototype
和__proto__
的区别:Javascript中全部的对象都是Object的实例,并继承Object.prototype
的属性和方法,也就是说,Object.prototype
是全部对象的父级。javascript
在对象建立时,就会有一些预约义的属性,其中定义函数的时候,这个预约义属性就是prototype
,这个prototype
是一个普通的对象。 而定义普通的对象的时候,就会生成一个__proto__
,这个__proto__
指向的是这个对象的构造函数的prototype
.java
function A () {}
let a = new A()
复制代码
当咱们声明一个函数A时就自动建立了prototype
对象。而a是构造函数A的实例,这时候a是一个实例对象,由于实例对象只有__proto__
属性, 因此a只有__proto__
属性,此属性指向A.prototype
。bash
因此:函数
// 每一个实例对象(object)都有一个私有属性(称之为__proto__)指向它的原型对象(prototype)
a.__proto__ === A.prototype // true
复制代码
这就是prototype
和__proto__
的区别。ui
咱们都知道对象都有一个toString方法。上述的实例化对象a也能够toString。而实例化对象a自己并无toString的方法,那他就会沿着它的__proto__向他的构造函数A的prototype对象去找,而这里也没有,那他就会继续沿着A.prototype.__proto__
向上找。而A.prototype.__proto__
指向的就是Object.prototype
。(这也同时也解释了为何全部的javascript对象都具备Object的基本方法。)this
a.toString() === Object.prototype.toString() // true
复制代码
这一层一层的连接关系就是原型链,层层向上直到一个对象的原型对象为 null(Object.prototype.__proto__ === null
)。根据定义,null 没有原型,并做为这个原型链中的最后一个环节。spa
用代码表示就是:.net
a.__proto__ === A.prototype // true
A.prototype.__proto__ === Object.prototype // true
==>
a.__proto__.__proto__ === Object.prototype // true
复制代码
有了上面的理论支持,再理解原型链继承就十分简单了prototype
function Parent(){
this.name = 'mike';
}
function Child(){
this.age = 12;
}
Child.prototype = new Parent(); // Child继承Parent,经过原型,造成链条
复制代码
这个时候Child.prototype
已是{ name: 'mike' }
了code
let childA = new Child() // 建立实例
console.log(childA) // { age: 12 }
复制代码
childA中并无name属性,可是根据咱们在上面讨论的,原型链会一层层向上找,因此:
childA.name === childA.__proto__.name === Child.prototype.name // true
console.log(childA.name) // mike
复制代码