1. 每个函数(箭头函数除外)都有prototype属性,该属性指向原型。
  2. 每个对象(null除外)都有__proto__属性,指向了创立了该对象的构造函数的原型。(注:函数也是对象)
  3. 对象能够通过__proto__来寻找不属于该对象的属性,__proto__将对象连接起来组成了原型链。

了解原型和原型链,上面这张图很重要:

依据下面这张图,可能失去如下等式:

// 一、对象的__proto__指向其构造函数的原型f1.__proto__ === Foo.prototype// 二、对象的__proto__指向其构造函数的原型f2.__proto__ === Foo.prototype// 三、Foo.prototype实质是一个对象,其构造函数是ObjectFoo.prototype.__proto__ === Object.prototype// 四、Foo是一般函数(函数也是对象,所以有__proto__属性),其构造函数是FunctionFoo.__proto__ === Function.prototype// 五、这一条比拟非凡,也很正当。Funcion既是对象又是函数(而且不是一般函数,是所有一般函数的构造函数)。// 因为是对象,所以有__proto__属性,指向其构造函数(本人)的原型。Function.__proto__ === Function.prototype// 六、同三Function.prototype.__proto__ === Object.prototype// 七、Object是所有对象的构造函数,是一个函数,函数的构造函数是FunctionObject.__proto__ === Function.prototype// 八、所有对象顺着原型链最终都会找到Object.prototype,而Object.prototype.__proto__ = null即是原型链的起点Object.prototype.__proto__ === null

下面的等式都分明了之后,上面这些等式应该也可能推导进去了:

Object.__proto__.__proto__ === Object.prototypeObject.__proto__.__proto__.__proto__ === nullFunction.__proto__.__proto__ === Object.prototypeFunction.__proto__.__proto__.__proto__ === null

其实在做推导时,抓住几个要害,就不容易被绕晕掉了:

  1. 函数也是对象
  2. 看到x.__proto__时,就要把x看成对象(哪怕它是个函数),继而想到“对象的__proto__指向其构造函数的原型”
  3. 看到x.prototype时,就要想到x必定是个函数,x.prototype作为一个整体示意函数x的原型,其实就是个对象