首先,要明确,在js中:
1、每个函数对象都有一个 prototype属性,我们称之为原型属性
2、每个对象都有一个 __proto__ 属性,(其实是指向他构造函数的原型)
3、所有的原型对象都有constructor属性,该属性对应创建所有指向该原型的实例的构造函数
4、函数对象和原型对象通过prototype和constructor属性进行相互关联.
在js中,“万物皆对象”,函数对象也是对象的一种。
对于新手来说,最难理解的就是prototype 和 __proto__ 之间的关系。
先看区别:(盗个个人觉得还不错的图)
看如下demo:
functionPerson(){
}
var will =newPerson()
它所对应的的原型图如下:
原型图解析:
1、 我们创建了一个 函数对象 叫做 Person,这个对象有 __proto__ 和 prototype属性
2、 Person.prototype 是该函数的原型对象,该对象有 constructor 属性指向原函数对象,和__proto__指向 他原函数对象的 “父” 函数的原型对象,即Object.Protytype.
3、 我们知道js中所有的对象都是继承自 Object,就是图中 的 function Object,该对象为 最顶级函数对象,所有的对象的__proto__属性最终都指向了该对象的原型对象。即Object.prototype
4、 另外所有的函数对象都是继承自 Function的原型,Object也是一个函数对象,所以Object.__protu__ === Function.prototype. 也是指向了 Function的原型
5、 对于Function 函数对象,他和所有其他函数对象一样有个__proto__指向了 Function.prototype, 而Function的原型中有constructor属性指向 Function对象。即 Function.__proto__ === Function.prototype. Function === Function.Prototype.constructor
6、 同样在 顶级对象Object 的原型属性中也有 constructor属性指向 顶级对象本身。即 Object === Object.prototype.constructor.
7、 再看Persopn函数对象,Person有个一 __proto__指向 Function的原型,有个prototype属性指向了 他自己的原型。在Person的原型中,有 constructor属性指向 Person,有__proto__属性指向了Object的原型,即 Person === Person.prototype.constructor。 Person.__proto__ === Function.prototype
8、 最后看一下通过Person创建的will对象。这个对象 有一个 __proto__属性指向它构造函数的原型。即will.__proto__ === Person.prototype
(ps: 以上说的可能有点啰嗦,但是需要你每一句都精度完之后,就应该能理解对象的原型和原型链,以及js中的继承关系)
原型链的行程原理我们已经分析完了,下面看一下一个示例demo:
varA=function(){};
var a =newA();
console.log(a.__proto__); //A {}(即构造器function A 的原型对象)
console.log(a.__proto__.__proto__);//Object {}(即构造器function Object 的原型对象)
console.log(a.__proto__.__proto__.__proto__);//null
上述代码的继承关系如下图:
补充:
浏览器查找js对象中的属性的顺序:
A、查找本对象中可枚举的属性,有的话就返回,没有的话执行B
B、再去查找父 __proto__,从父元素继承的属性中可枚举的属性,有的话就返回,没有的话执行C
C、父对象的原型中也没有对象的属性的话,继续找找父元素的__proto__,查找父元素从父父元素(父元素的父元素)的可枚举属性,有的话就返回,没有的话继续按照继承原型链向上查找,直到顶级对象 Object
D、如果顶级对象Object中的可枚举属性中有该属性的话就返回,没有的话就返回undefined