大纲
[[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
- 每个对象都有
__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的属性,但是最后输出来的是实例属性上的值。
当我们读取一个属性的时候,如果在实例属性上找到了,就读取它,不会管原型属性上是否还有相同的属性,这其实就是属性屏蔽
。即当实例属性和原型属性拥有相同名字的时候,实例属性会屏蔽原型属性,记住只是屏蔽,不会修改,原型属性那个值还在。
- __proto__这个属性其实指向了[[prototype]],但是[[prototype]]是内部属性,我们并不能访问到,所以使用__proto__来访问。
-
Foo的[[Prototype]]是Function.prototype。(图一:3)
-
虽然无法访问[[prototype]],但还是有方法去验证它的存在的。
- Object.getPrototypeOf这个方法返回[[Prototype]]的值,可以获取到一个对象的原型
Person.prototype.isPrototypeOf(person1) // true
Person.prototype.isPrototypeOf(person2) // true
Object.prototype
Object.prototype
是原型链的顶端,所有对象从它继承了包括toString等等方法和属性。Object.prototype的__proto__指向null
,Object.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而产生。