JS 的原型的深层原理

5 min read
# 记录# 技术
View

了解 JS 的原型和原型链,可以深刻了解 JS 的对象的根本原理,也可以避免在编码时遇到的无意识修改了对象原型导致其他对象的原型也被修改的问题。

JS 的原型和原型链是什么

原型链:JS 的实例对象(object)都有一个私有属性 __proto__,用来指向构造这个对象的构造函数的原型对象 prototype,该原型对象 prototype 也有 __proto__ 指向它的构造函数的 prototype。这样一直做指向链接,直到最后一个对象的 prototype 指向 null,根据定义 null 并不具备原型,所以这个对象是这条原型链上的顶层对象,也是此原型链的最后一环节。

原型:是指实例对象的私有属性 __proto__ 指向的它的构造函数的 prototype

原型定义并实现了一个新创建的对象所必须包含的成员列表。与传统的 OOP 中的 class 不同,OOP 中的 class 定义了创建实例的过程,而 JS 的原型对象为所有对象的实例共享。因此实例也共享了原型对象的成员。

对象通过内部属性 __proto__ 绑定原型,于是对象便有了两种成员类型:实例成员 (own property)原型成员。OwnProperty 存在与对象实例中,原型成员则集成了原型对象。

let obj = {
  title: 'title',
  name: 'name'
}
console.dir(obj)

在浏览器控制台输出为

检索对象中的 OwnPropotype

obj.hasOwnProperty('title') // true
obj.hasOwnProperty('hasOwnProperty') // false

hasOwnProperty 方法引用于继承原型 Object 的,用于检索实例成员的,这方法将会过滤掉原型上的成员

检索对象中的所有属性

可以使用 in 操作符检索所有属性,包括原型的成员。

'hasOwnProperty' in obj // true

原型链

对象的原型决定了实例的类型,默认情况下,所有对象都是 Object 的实例,并继承了其所有方法,例如 hasOwnProperty

如果需要检索对象的某个属性,在实例成员中找不到,便会查找对象原型,这个过程会一直检索到最根本的对象的原型。这个链状关系被成为原型链。

原型链修改

function Animal(name) {
  this.name = name;
}
Animal.prototype.sayName = function() {
  console.log(this.name)
}

let cat = new Animal('cat');
let dog = new Animal('dog');

cat.sayName();
dog.sayName();

上述例子中,cat 和 dog 都是基于函数 Animal 构造的实例对象,cat 和 dog 的原型 (__proto__) 是 Animal.prototype,Animal.prototype 是 Object。

参考

  • 高性能 JavaScript
  • JavaScript 高级程序设计
Table of Contents