1.帮你完全搞懂JS中的prototype、__proto__与constructor(图解)javascript
以前也尝试总结过 js 中的 __proto__ 、 prototype 以及原型链相关的资料(JS 中的原型 -- prototype、__proto__ 以及原型链),不过彼时受限于经验等因素,没有多少条理,同时也存在诸多的的疑点。html
学习嘛,就是一个不断推翻本身的过程,本次总结以下:java
如下例子贯穿全文...chrome
function Foo(age) { this.age = age; } let f1 = new Foo(16);
先来张总体图解(原图较大,建议新标签页内观看):浏览器
看着这花花绿绿的线条,头真的很大...不过不要紧,分解过来看。函数
注意: 图中的 '()' 仅表明这是一个函数对象,并不是执行函数运算符。
post
__proto__ 在 ECMA 标准中是 [[Prototype]] ,各家浏览器的实现不同,在 chrome 中就是 __proto__ ,稍微留意下便可。学习
__proto__ 属性,当中存放(指向)着的是一个对象,粗略地讲就是以 “{ key: value }” 这种形式存在的对象(这里主要的为和 js 中的函数对象区分开来)。this
__proto__ 这个属性,理应是 “{k: v}” 对象所独有的,可是由于 js 中万物皆对象,因此 js 函数也是一种对象,因此函数也一样拥有这个属性,也正是由于这样,极容易产生困惑。
url
咱们从总图中把 __proto__ 单独抽出来:
如上图所示,一个对象(f1)的 __proto__ 指向的另外一个对象的,即指向它们的原型对象(也能够理解为父对象)。
这个属性的做用是当访问一个对象的属性时,若是该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(父对象)里找,若是父对象也不存在这个属性,则继续往父对象的 __proto__ 属性所指向的那个对象(爷爷对象)里找,若是还没找到,则继续往上找…直到原型链顶端null(原始人。。。),再往上找就至关于在null上取值,会报错。
经过这样一种链条式的值查找,就是咱们常见的原型链,同时,这也是咱们模拟继承的经常使用方法。
prototype 属性,函数独有,其存放(指向)的一样是一个对象。
从总图中将 prototype 抽出来:
prototype 中存放的一样是一个对象,这个对象的含义是函数的原型对象,也就是以这个函数做为构造函数(其实全部函数均可以做为构造函数)所建立的实例的原型对象,即 f1.__proto__ === Foo.prototype,这两个属性均指向同一个对象。
prototype 的做用是包含能够由特定类型的全部实例共享的属性和方法,也就是让该函数所实例化的对象们均可以找到公用的属性和方法。任何函数在建立的时候,其实会默认同时建立该函数的prototype对象。
constructor 属性,和 __proto__ 同样,理应是对象独有,不过嘛,由于 js 因此 函数也有,可是不经常使用,故留意下便可。
constructor 属性(变量),当中存放(指向)的是一个函数。
constructor 中存放的这个函数,就是该对象的构造函数,如对象 f1 以 Foo 为构造函数,那么 f1.constructor == Foo // true 。
从上图中能够看到,全部的箭头都指向 Function 这个函数,而且 Function 的 constructor 是指向本身,故 constructor 属性的重点就是 Function 这个函数。如: Foo.constructor == Function // true 。
从第 三 点咱们知道,任何函数在建立的时候,其实会默认同时建立该函数的prototype对象。而在建立的这个 prototype 对象的时候,其中的 constructor 会显示指向这个函数,即上图中的 Foo.prototype.constructor == Foo
以上为本次总结的内容,若有缺陷,还望斧正。