走一遍流程图,了解 [[prototype]]、__proto__、prototype究竟是什么

1,288 阅读2分钟

大纲

[[prototype]]、proto、prototype究竟是什么。遍走这个经典的流程图,遍解释它们的含义。

写在最前面

原型链的尽头(root)是Object.prototype。所有对象均从Object.prototype继承属性。

prototype

每个函数都有prototype属性(图一:1),也只有函数才有prototype属性。除了 Function.prototype.bind(),该属性指向原型。

var obj = {name: 'aaa'};
obj.prototype; // undefined

Foo是一个函数,所有的函数默认都会拥有一个prototype,值是一个有constructor属性的对象,这个属性关联的是函数Foo(图一:2)。

prototype.constructor

function Foo() { 
    ...
}
Foo.prototype.constructor === Foo; // true

constructor使我们能以构造函数的形式去new这个函数,JS就会创建该构造函数的实例并给所创建函数(图里是f1)一个内部的__proto__。(图二:4)

function Person() {
    ...
};
var person1 = new Person();
console.log(person1.constructor === Person); // true

person1作为Person的实例,没有.constructor属性。是通过__proto__原型链在原型Person.prtototype上面找到的。

new 的过程
  • 新生成了一个对象
  • 链接到原型
  • 绑定 this
  • 返回新对象

proto

  1. 每个对象都有__proto__,指向构造函数的prototype,继承prototype的所有属性和方法。对象可以通过__proto__来寻找不属于该对象的属性,__proto__将对象连接起来组成了原型链。
function Foo() {// 原型属性

};
Foo.prototype.name = "Yuan";

var f1 = new Foo();

console.log(f1.name);// 'Yuan';

f1.name = 'Y';

console.log(f1.name);// Y

上面代码中在实例属性和原型属性都有一个名为name的属性,但是最后输出来的是实例属性上的值。

当我们读取一个属性的时候,如果在实例属性上找到了,就读取它,不会管原型属性上是否还有相同的属性,这其实就是属性屏蔽即当实例属性和原型属性拥有相同名字的时候,实例属性会屏蔽原型属性,记住只是屏蔽,不会修改,原型属性那个值还在。

  1. __proto__这个属性其实指向了[[prototype]],但是[[prototype]]是内部属性,我们并不能访问到,所以使用__proto__来访问。

  1. Foo的[[Prototype]]是Function.prototype。(图一:3)

  2. 虽然无法访问[[prototype]],但还是有方法去验证它的存在的。

  • Object.getPrototypeOf这个方法返回[[Prototype]]的值,可以获取到一个对象的原型
Person.prototype.isPrototypeOf(person1) // true
Person.prototype.isPrototypeOf(person2) // true

Object.prototype

Object.prototype是原型链的顶端,所有对象从它继承了包括toString等等方法和属性。Object.prototype的__proto__指向nullObject.prototype没有原型(5)

(f1)函数对象也是对象,所以也有proto属性,连接它的原型。原型对象Foo.prototype的原型就是Object.prototype。(6)

但Object本身是构造函数有constructor属性(7),继承了Function.prototype,是Function的实例。(8)

Function.prototype和Function.__proto__为同一对象。而Function也是对象,继承了Object.prototype。Function.prototype直接继承root(Object.prototype)。(9)

Object instanceof Function // true
Function instanceof Object // true

那么是先有了Object还是先有了Function?

ES规范:

Function本身就是函数,Function.__proto__是标准的内置对象Function.prototype

Function.prototype.__proto__是标准的内置对象Object.prototype

最后总结:先有Object.prototype(原型链顶端),Function.prototype继承Object.prototype而产生,最后,Function和Object和其它构造函数继承Function.prototype而产生。

参考资料:github.com/KieSun/Blog…