发布于 2026-01-06 0 阅读
0

理解 JavaScript 中的类 (ES5) 和原型继承

理解 JavaScript 中的类 (ES5) 和原型继承

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

const me = new Person('Joe', 20);

console.log(me); // {name: 'Joe', age: 20}

简而言之,上面的代码片段创建了一个可以拥有多个实例的 Person 类。按照惯例,JavaScript 中的函数式类名以大写字母开头。

让我们深入探讨一下这里发生了什么?如何将普通函数用于类?🤔🤔

这个Person函数和其他函数一样,直接调用时会直接返回,undefined因为我们没有显式地从中返回任何值。但真正的奥妙在于new第 1 行的关键字var me = new Person('Joe', 20)。让我们来理解这个奥妙——当我们使用关键字初始化一个函数
时,会发生以下几个步骤:new

  1. {}创建一个空对象。
  2. Person调用方法是将对象的引用传递给它:Person.call({}, 'Joe', 20)
  3. 现在“内部”Person this指的是上一步中传递的对象。
  4. 使用以下方法将对象的 proto 设置为函数的原型:{}.__proto__ = Person.prototype.
  5. 最后返回对象,这就是我们接下来要讨论的内容。me

概念说明:JavaScript 中的每个函数都有一个原型对象。这就是它的用法Array.prototype.map。而且每个对象__proto__本身也有一个对象。想了解更多信息,请观看精彩视频《探索 JavaScript》

由于 `and`prototype和 `or`__proto__指的是同一个对象,因此无论何时向 `or` 添加一个新函数,prototype它都会在所有实例上可用。

Person.prototype.greet = function() {
  console.log('Hi', this.name);
}

me.greet(); // Hi Joe

const you = new Person('Alice', 22);
you.greet(); // Hi Alice

到目前为止,我们已经了解了如何在 JavaScript 中创建类。接下来,让我们了解如何在 JavaScript 中继承类。

让我们创建一个名为 Employee 的新类,它继承自 Person 类。

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

// create Employee prototype from Person prototype
Employee.prototype = Object.create(Person.prototype);

const joe = new Employee('Joe', 22, 'Developer');
console.log(joe.name); // Joe
joe.greet(); // Hi Joe

哇,我们终于继承了 Person 类来创建 Employee 类,而且我们不必重写greet函数。

让我们看看刚才发生了什么?

  1. 我们创建这个Employee班级的方式和我们创建班级的方式一样Person
    • 在我们的员工类中,我们通过传递引用来调用 Person 类this。这就像super在 ES6 类中使用关键字一样。
  2. 这是最重要的部分。我们正在根据Person 原型重新创建Employee 原型,以便访问该类中所有可用的方法Person

现在你可能会问,为什么Object.create不直接将 Person 原型分配给 Employee,而是要使用继承 Person 呢?
这是因为我们不希望 Person 和 Employee 共享同一个原型,因为在 JavaScript 中,对象是被引用的。这正是继承 Person 的意义所在。

这就是我们在 JavaScript 中使用原型继承的方式。新的 ES6 类本质上是对其的一种语法糖。这才是底层实际发生的原理。

PS:您可以在这里找到完整的代码:GitHub 仓库

文章来源:https://dev.to/_hridaysharma/understanding-classes-es5-and-prototypal-inheritance-in-javascript-n8d