🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 原型链 **3.1 原型** 每一个JavaScript对象(null除外)都和另一个对象相关联,也可以说,继承另一个对象。另一个对象就是我们熟知的“原型”(`prototype`),每一个对象都从原型继承属性。只有null除外,它没有自己的原型对象。 我们可以通过`__proto__`(首尾都是双下划线)来获取实例的原型对象。 注意:`__proto__`连接的是实例与构造函数的原型对象之间,而不是实例与构造函数之间。 所有通过对象直接量创建的对象都具有同一个原型对象,并可以通过JavaScript代码`Object.prototype`获得对原型对象的引用。 通过关键字new和构造函数调用创建的对象的原型就是构造函数的`prototype`属性的值。比如:通过new Object()创建的对象继承自Object.prototype;通过new Array()创建的对象的原型就是Array.prototype。 没有原型的对象为数不多,`Object.prototype`就是其中之一,它不继承任何属性。 所有的内置构造函数都具有一个继承自`Object.prototype`的原型。 **3.1 原型链** 在JavaScript中,原型链是实现继承的主要方式。 原型链的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。 可用`__proto__`属性来获取或设置对象的原型。 每个构造函数都有一个原型对象(prototype),原型对象本身也是对象,所以它也有自己的原型,而它本身的原型对象也有自己的原型,这样层层递进,就形成了一条链,这个链就是**原型链**。 JavaScript引擎在访问对象的属性时,会先在对象本身中查找,如果没有找到,则会去原型链中查找,如果找到,则返回值,如果整个原型链中都没有找到这个属性,则返回undefined。 ``` var person = { name: 'human' }; var person1 = { name: 'tg', __proto__: person }; var person2 = { __proto__: person }; console.log(person1.name); // "tg" console.log(person2.name); // "human" console.log(person1.id); // undefined ``` 从上面例子的运行结果,我们也可以看出原型链的运行机制:从对象本身出发,沿着`__proto__`查找,直到找到属性名称相同的值(没有找到,则返回undefined)。 所有对象都继承自`Ojbect`,而这个继承也是通过原型链实现的。所有函数的默认原型都是Object的实例,因此默认的原型都会包含一个内部指针,指向`Object.prototype`。而`Object.prototype`的`__proto__`的属性值为null,标志着原型链的结束。 **3.2 原型和实例** 有两种方式来确定原型和实例之间的关系: - 使用`instanceof`操作符 ``` function Person(){} var person = new Person(); console.log(person instanceof Object); // true console.log(person instanceof Person); // true ``` - 使用`isPrototypeOf()`方法。 ``` console.log(Object.prototype.isPrototypeOf(person)); // true console.log(Person.prototype.isPrototypeOf(person)); // true ```