返回

深入浅出剖析__proto__和prototype之间的关系,揭开JavaScript运行机制

前端

在JavaScript的世界中,prototype__proto__ 是两个经常被提及的概念。它们密切相关,同时也是JavaScript运行机制的重要组成部分。为了更好地理解它们,我们需要从对象的创建和继承说起。

JavaScript中的对象创建和继承

JavaScript中的对象可以通过两种方式创建:通过对象字面量或通过构造函数。

  • 对象字面量 :使用花括号({})创建的对象。例如:
const person = {
  name: "John Doe",
  age: 30,
};
  • 构造函数 :使用new调用函数创建的对象。例如:
function Person(name, age) {
  this.name = name;
  this.age = age;
}

const person = new Person("John Doe", 30);

当通过构造函数创建对象时,JavaScript会自动在对象中创建一个名为 __proto__ 的属性,指向该对象的构造函数的 prototype 属性。因此,对于上例中的 person 对象,person.__proto__ 将指向 Person.prototype

prototype和__proto__之间的关系

prototype__proto__ 之间的联系十分紧密,我们可以通过一个简单的示例来说明。

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.sayHello = function() {
  console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};

const person = new Person("John Doe", 30);

person.sayHello(); // Hello, my name is John Doe and I am 30 years old.

在这个示例中,我们首先定义了一个 Person 构造函数,并在其 prototype 属性上添加了一个 sayHello 方法。然后,我们使用 new 关键字创建了一个 person 对象。当我们调用 person.sayHello() 时,JavaScript 会在 person 对象中查找 sayHello 方法。由于 person 对象中没有 sayHello 方法,JavaScript 会沿 person 对象的原型链向上查找,直到找到 Person.prototype。在 Person.prototype 中找到了 sayHello 方法,JavaScript 就会调用该方法。

如何利用prototype和__proto__实现对象继承

JavaScript 中的对象继承是通过 prototype__proto__ 实现的。当我们通过构造函数创建对象时,JavaScript 会自动在对象中创建一个 __proto__ 属性,指向该对象的构造函数的 prototype 属性。因此,子对象的 __proto__ 属性指向父对象的 prototype 属性,从而实现了对象继承。

例如,如果我们想要创建一个 Student 类,并让 Student 类继承 Person 类,我们可以这样做:

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.sayHello = function() {
  console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};

function Student(name, age, major) {
  Person.call(this, name, age);
  this.major = major;
}

Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

const student = new Student("John Doe", 30, "Computer Science");

student.sayHello(); // Hello, my name is John Doe and I am 30 years old.

在这个示例中,我们首先定义了一个 Person 类,并在其 prototype 属性上添加了一个 sayHello 方法。然后,我们定义了一个 Student 类,并在其构造函数中调用 Person.call(this, name, age); 来继承 Person 类的属性和方法。接下来,我们使用 Object.create(Person.prototype) 来创建 Student.prototype,并将其赋值给 Student.prototype。最后,我们使用 Student.prototype.constructor = Student; 来修复 Student 类的 constructor 属性,使其指向 Student 函数。

现在,当我们创建一个 student 对象时,JavaScript 会自动在 student 对象中创建一个 __proto__ 属性,指向 Student.prototype。由于 Student.prototype 继承了 Person.prototype,因此 student 对象也继承了 Person 类的属性和方法。