js原型链简析

206 阅读2分钟

当你在 JavaScript 中创建一个对象时,它实际上是基于构造函数创建的。每个构造函数都有一个原型对象,该对象包含在使用该构造函数创建的所有对象之间共享的属性和方法。每个对象都有一个指向其构造函数的内部 [[Prototype]] 属性。

当你尝试访问一个对象的属性或方法时,JavaScript 引擎会首先在该对象自身上查找。如果该属性或方法不存在,则会继续在对象的 [[Prototype]] 属性指向的原型对象上查找。如果原型对象也没有该属性或方法,则会继续查找原型对象的 [[Prototype]] 属性指向的原型对象,直到找到该属性或方法,或者到达原型链的末尾。

原型链的结构实际上是一条链式结构,其中每个对象都有一个指向其原型对象的内部 [[Prototype]] 属性。这条链的末端是 Object.prototype,它是所有 JavaScript 对象的原型对象。

下面是一个示例:

// 定义一个构造函数
function Person(name, age) {
  this.name = name;
  this.age = age;
}

// 向 Person 构造函数的原型对象中添加一个方法
Person.prototype.sayHello = function() {
  console.log(`Hello, my name is ${this.name}`);
};

// 创建一个 Person 对象
const person1 = new Person('Alice', 25);

// person1 对象的 [[Prototype]] 属性指向 Person 构造函数的原型对象
console.log(person1.__proto__ === Person.prototype); // true

// Person 构造函数的原型对象的 [[Prototype]] 属性指向 Object 构造函数的原型对象
console.log(Person.prototype.__proto__ === Object.prototype); // true

// Object 构造函数的原型对象没有 [[Prototype]] 属性
console.log(Object.prototype.__proto__); // null

// 调用 person1 对象上的 sayHello 方法
person1.sayHello(); // 输出 "Hello, my name is Alice"

在上面的示例中,我们创建了一个名为 Person 的构造函数,并向其原型对象中添加了一个名为 sayHello 的方法。然后,我们创建了一个 Person 对象 person1,并调用了该对象上的 sayHello 方法。JavaScript 引擎首先在 person1 对象自身上查找该方法,然后在 Person.prototype 对象上查找,最后在 Object.prototype 对象上查找,最终找到了该方法并成功调用。