Skip to content

js 原型链

JavaScript 的原型链是理解对象间继承和属性查找机制的核心概念。在 JavaScript 中,每一个对象都有一个内部属性,叫做[[Prototype]],它指向另一个对象,这就是原型对象。原型链就是通过这个[[Prototype]]属性连接的一系列原型对象,它使得对象可以继承另一个对象的属性和方法。

原型对象

每个函数在 JavaScript 中都有一个 prototype 属性,这个属性是一个对象,用于作为由该函数构造的对象的原型。当你使用 new 关键字创建一个对象时,这个新对象的[[Prototype]]就会指向构造函数的 prototype 对象。

原型链查找机制

当你试图访问一个对象的属性或方法时,JavaScript 引擎首先在该对象本身查找这个属性或方法。如果没找到,它会沿着原型链向上查找,直到找到这个属性或方法,或者到达原型链的末端(通常是 Object.prototype,因为这是所有对象原型的基底)。

如果在原型链的任何一点上找到了这个属性或方法,查找就会停止,这个属性或方法就会被返回。如果在原型链的末端还没有找到,那么就会报错,因为这意味着该属性或方法不存在。

示例

假设我们有两个构造函数 Person 和 Student,其中 Student 继承自 Person:

js
function Person(name) {
  this.name = name;
}

Person.prototype.sayHello = function () {
  console.log("Hello, my name is " + this.name);
};

function Student(name, grade) {
  Person.call(this, name); // 使用call调用父类构造函数
  this.grade = grade;
}

// 设置继承关系
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

Student.prototype.study = function () {
  console.log(this.name + " is studying.");
};

在这个例子中,Student 对象可以访问 sayHello 方法,因为它不在 Student 对象本身,也不在 Student.prototype 对象上,但是在 Person.prototype 对象上,所以通过原型链可以找到。

prototype 与 __proto__

属性主要与构造函数和类关联。当你定义一个时,JavaScript 会自动为其添加一个 prototype 属性,这个属性是一个对象,用于存放可以被该构造函数创建的所有实例共享的属性和方法。当你使用 new 关键字创建一个对象时,这个新对象的[[Prototype]](内部属性,不可直接访问)会指向构造函数的 prototype 对象。

prototype 属性是构造函数的属性,用于存放所有实例共享的属性和方法。

js
function MyConstructor() {
  // constructor logic
}

MyConstructor.prototype.myMethod = function () {
  console.log("Called myMethod");
};

const myInstance = new MyConstructor();
myInstance.myMethod(); // 输出: "Called myMethod"

在这个例子中,myMethod 是 MyConstructor.prototype 上的一个方法,所有 MyConstructor 的实例都可以访问它。

是一个,它直接指向该对象的原型([[Prototype]])。在现代 JavaScript 中,__proto__提供了一个直接访问对象原型链的途径,但要注意,这不是一个标准的属性,而是由 JavaScript 引擎实现的,主要用于调试和教育目的。

__proto__属性是对象的属性,指向该对象的原型对象,用于原型链的查找。

js
const obj = {};
console.log(obj.__proto__); // 输出: [Object: null prototype] {}

obj.__proto__ = { hello: "world" };
console.log(obj.hello); // 输出: "world"

在这个例子中,我们直接修改了 obj 的proto属性,使其指向一个包含 hello 属性的新对象。然后,我们就可以通过 obj 访问 hello 属性。

在 ES6 中引入的类语法,prototype 的概念依然存在,但是__proto__的使用在严格模式下被限制,以防止意外修改原型链。对于现代 JavaScript 编程,更推荐使用 方法来安全地访问和修改原型链。

Released under the MIT License.