深入理解Javascript中原型链机制
原型链机制prototype chain
是Javascript设计中较为重要的内容,对象之间通过原型链建立彼此之间的关系。在Kyle Simpson’s所著的《You Don’t Know JS》一书中介绍了两种Javascript中组织代码的方式:OLOO(Object Linked to Other Object)
以及Prototype Design Pattern
。两种设计模式均围绕Javascript中的原型链机制给出了不同思想的解释。因此正确理解Javascript中的原型链机制至关重要。
一、_proto_
Object.prototype的__proto__属性是一个访问器属性(一个getter函数和一个setter函数),它公开访问它的对象的内部[[Prototype]](对象或null)。
目前__proto_属性已经被大多数浏览器厂商所支持,并且成为ES6的标准规范。下文中所做的演示仅仅是想说明原型链的原理,在生产环境以及平时的编码中尽量避免对 _proto 的直接操作,因为这可能涉及到性能问题。
[[Prototype]]是实现JS中两个对象建立联系(或者说实现继承)的关键,通过[[Prototype]]可以建立多个对象之间的联系,从而对象之间根据彼此之间的联系成为链状,称之为原型链。
通俗的讲,通过[[Prototype]]可以获得与该对象相关联对象的相关属性。但是通过[[Prototype]]可以获得相关联对象的哪些属性呢,又是如何建立两个对象之间连接的呢?
通过以下三种方式可以直接建立两个对象的链接:
new构造函数
1
2
3
4
5
6
7
8
9
10function Person(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
let p1 = new Person('monster1935', '25', 'male');
Person.__proto__ === Function.prototype;// true
p1.__proto__ === Person.prototype;// true如上面的代码所示,这种方式建立了实例对象与构造函数对象(或者暂且称之为类)的关系。实例对象
p1
通过__proto__可以访问Person
对象的prototype对象中的属性。
Object.create()
1
2
3
4
5
6
7let obj2 = {
name: 'monster1935'
};
let obj1 = Object.create(obj2);
obj1.name; // monster1935
obj1.__proto__ === obj2;// true如上面的代码所示,
Object.create(obj2)
以obj2为原型,创建了obj1与obj2的联系。Object.setPrototypeOf()
设置一个指定的对象的原型 ( 例如,内置的 [[Prototype]]属性)到另一个对象或 null。和设置__proto__一样会带来性能问题,尽量使用Object.create()来动态设置对象的原型。
二、prototype
prototype属性代表原型对象。并非所有的对象都有该属性,在Javascript中创建对象的几种方式讨论一文中给出过关于Javascript中对象的分类,Javascript中的内部对象都是默认含有prototype属性的,自定义对象是没有该属性的。
三、深入理解原型链
如上图所示,图中给出了Javascript中原型链的图示。
1 | Object.prototype.__proto__ === null; |
如上所示,
- 所有原型对象的(除Object外)均指向
Object.prototype
,因为他们的本质也是对象。所有对象均继承自Object.prototype
。 - Object.prototype指向null,为原型链的终点。
- 所有内部对象的原型均指
Function.prototype
,即他们都是继承自Function,**Function的原型也指向自己的原型对象即Function.__proto__ === Function.prototype
**。 - 构造函数对象默认含有prototype属性,实例对象的原型默认指向构造函数对象的原型对象即
p1.__proto__ === Person.prototype;
。
参考文章:
深入理解Javascript中原型链机制
https://monster1935.cn/blog/2017/03/20/深入理解Javascript中原型链机制/