Heim  >  Artikel  >  Web-Frontend  >  Warum Nodejs nicht erben können

Warum Nodejs nicht erben können

PHPz
PHPzOriginal
2023-04-26 09:06:54465Durchsuche

Node.js (im Folgenden als Node bezeichnet) hat sich in den letzten Jahren zu einer der beliebtesten serverseitigen JavaScript-Plattformen weltweit entwickelt. Obwohl es über viele Funktionen verfügt, sei es die Laufgeschwindigkeit, den Speicherbedarf oder die unterstützten Bibliotheken und Frameworks, weist Node in einigen Aspekten dennoch seine eigenen Einschränkungen auf. Eines der größten Probleme besteht darin, dass Node.js nicht vererbt werden kann.

In der objektorientierten Programmierung ist Vererbung eine wichtige Funktion, die es Entwicklern ermöglicht, eine Basisklasse (übergeordnete Klasse) und darauf basierend weitere Unterklassen zu erstellen. Diese Unterklassen können Methoden in der übergeordneten Klasse überschreiben oder neue Methoden hinzufügen, um die Funktionalität zu erweitern und wiederzuverwenden. Im Kontext von Node.js erfolgt die Vererbung normalerweise in Form des Kopierens von Eigenschaften und Methoden zwischen Klassen. Aufgrund des asynchronen Modells von Node.js und seines Zusammenspiels mit der Flexibilität von JavaScript ist die Vererbung in Node jedoch nicht sehr intuitiv und manchmal schwierig zu implementieren. In diesem Artikel wird untersucht, warum Node.js nicht erbt, und es werden einige Alternativen aufgezeigt.

1. Das Problem der Implementierung der Vererbung in Node.js

Das Problem der Implementierung der Vererbung in Node.js besteht aus zwei Schlüsselfaktoren:

  1. Asynchrones Programmiermodell

Eines der Merkmale von Node.js ist asynchrones Programmiermodell, das eng mit JavaScript verwandt ist. Da Node.js Single-Threaded ist, muss es ein asynchrones Modell verwenden, um mehrere Client-Anfragen und andere asynchrone Aufgaben zu verarbeiten. Das asynchrone Modell macht Node.js effizienter, steht jedoch im Widerspruch zur geerbten Implementierung. Denn bei der asynchronen Programmierung erfolgen Funktionsaufrufe auf Basis von Timern. Nach dem Aufruf einer asynchronen Funktion läuft das Programm weiter, bis der asynchrone Rückruf abgeschlossen ist, bevor es zur Funktion zurückkehrt.

Betrachten Sie den folgenden Codeabschnitt:

class Person {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log(`Hello, my name is ${this.name}.`);
  }
}

class User extends Person {
  constructor(name, email) {
    super(name);
    this.email = email;
  }

  static log(email) {
    console.log(`User ${email} logged in.`);
  }

  login() {
    User.log(this.email);
    this.greet();
  }
}

const alice = new User('Alice', 'alice@example.com');
alice.login();

In diesem Beispiel haben wir eine Klasse Person und eine weitere Klasse User, die von Personerbt > >. Wenn wir die login-Methode für eine User-Instanz aufrufen, wird zunächst eine für die User-Klasse eindeutige log-Methode aufgerufen aufgerufen und dann die Methode greet der übergeordneten Klasse aufrufen. Da die Funktion jedoch asynchron ausgeführt wird, wird das Ergebnis nicht unseren Erwartungen entsprechen: Person 类和另一个类 User,它继承自 Person。当我们对一个 User 实例调用 login 方法时,会先调用一个 User 类独有的 log 方法,然后调用父类的 greet 方法。但由于函数是异步执行的,结果将不如我们所愿:

User alice@example.com logged in.
undefined

实际上,调用顺序是不正确的。由于 this.greet 是基于异步行为调用的,因此该方法的执行是在异步 User.log 方法的回调后进行的。这就是为什么 undefined 是打印在屏幕上的原因。

  1. 面向对象的JavaScript

第二个问题,是 JavaScript 自身对面向对象程序设计模式的支持。 JavaScript 不是一种传统的面向对象语言,它使用一种基于原型的对象模型,而不是使用基于类的对象模型。原型模型并不像继承那样直接支持类继承,如果想在 Node.js 中实现继承,就需要使用一些 JavaScript 的面向对象编程技巧。

在基于原型的继承模式中,开发者需要使用 Object.create() 方法来创建对象,并将其作为一个原型传递给子类。这种继承模式的优点是更加灵活,因为它允许您不仅继承类的方法,而且还可以继承属性。

以下是一个基于原型的示例:

class Person {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log(`Hello, my name is ${this.name}.`);
  }
}

const User = Object.create(Person.prototype, {
  email: { value: null, enumerable: true, writable: true }
});

User.constructor = User;

User.constructor('Tom', 'tom@example.com');

console.log(User);
User.greet();

在这个例子中,我们手动创建了一个对象,然后将其原型指向 Person.prototype。在定义User的时候,我们没有直接继承 Person,而是使用了 Object.create 方法创建了一个基于父类原型的对象。User 通过User.constructor函数调用注册用户。

二、解决方案

尽管 Node.js 有一些限制,但还有一些解决方案可以实现继承的功能。这里我们来介绍一些常见的解决方案:

  1. 基于模块的继承

Node.js 具有基于模块的架构,可以使用该模型创建实现继承的模块。Node.js 的模块系统允许您在不同的 JavaScript 文件中导入函数、对象和类,并将它们合并成一个单独的模块。实现继承的方式是创建父类模块和子类模块,并在子类模块中使用父类模块的函数、对象和类。

这里有一种例子,实现继承Person 类

//person.js
module.exports = class Person {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log(`Hello, my name is ${this.name}.`);
  }
};

//user.js
const Person = require('./person');

class User extends Person {
  constructor(name, email) {
    super(name);
    this.email = email;
  }

  static log(email) {
    console.log(`User ${email} logged in.`);
  }

  login() {
    User.log(this.email);
    this.greet();
  }
}

const user = new User('Tom', 'tom@example.com');
user.login();

在这个例子中,我们有一个 Person 模块和一个 User 模块,后者继承自前者。请注意,我们在 User 模块中使用了 require('./person') 导入了 Person 模块,并使用了 extends PersonUser 继承自 Person。最后,我们创建了一个 User 对象并试图调用 greet

class Person {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log(`Hello, my name is ${this.name}.`);
  }
}

class User extends Person {
  constructor(name, email) {
    super(name);
    this.email = email;
    this.proxy = new Proxy(this, {
      get(target, propKey) {
        return target[propKey] || target.__proto__[propKey];
      },
    });
  }

  static log(email) {
    console.log(`User ${email} logged in.`);
  }

  login() {
    User.log(this.email);
    this.proxy.greet();
  }
}

const user = new User('Tom', 'tom@example.com');
user.login();
Tatsächlich ist die Aufrufreihenfolge falsch. Da this.greet auf der Grundlage asynchronen Verhaltens aufgerufen wird, erfolgt die Ausführung dieser Methode nach dem Rückruf der asynchronen Methode User.log. Aus diesem Grund wird undefiniert auf dem Bildschirm angezeigt.
  1. Objektorientiertes JavaScript

Das zweite Problem ist JavaScripts eigene Unterstützung für das objektorientierte Programmiermuster. JavaScript ist keine traditionelle objektorientierte Sprache und verwendet ein prototypbasiertes Objektmodell anstelle eines klassenbasierten Objektmodells. Das Prototypmodell unterstützt die Klassenvererbung nicht direkt. Wenn Sie die Vererbung in Node.js implementieren möchten, müssen Sie einige objektorientierte Programmierkenntnisse in JavaScript verwenden.

Im prototypbasierten Vererbungsmuster müssen Entwickler die Methode Object.create() verwenden, um ein Objekt zu erstellen und es als Prototyp an Unterklassen zu übergeben. Der Vorteil dieses Vererbungsmusters besteht darin, dass es flexibler ist, da Sie nicht nur die Methoden der Klasse, sondern auch die Eigenschaften erben können. 🎜🎜Hier ist ein prototypbasiertes Beispiel: 🎜rrreee🎜In diesem Beispiel erstellen wir manuell ein Objekt und verweisen seinen Prototyp dann auf Person.prototype. Bei der Definition von User haben wir Person nicht direkt geerbt, sondern die Methode Object.create verwendet, um ein Objekt basierend auf dem Prototyp der übergeordneten Klasse zu erstellen. . Der Benutzer registriert Benutzer über User.constructor-Funktionsaufrufe. 🎜🎜2. Lösung🎜🎜Obwohl Node.js einige Einschränkungen aufweist, gibt es einige Lösungen, um geerbte Funktionen zu erreichen. Hier stellen wir einige gängige Lösungen vor: 🎜🎜🎜Modulbasierte Vererbung🎜🎜🎜Node.js verfügt über eine modulbasierte Architektur, und Sie können dieses Modell verwenden, um Module zu erstellen, die die Vererbung implementieren. Mit dem Modulsystem von Node.js können Sie Funktionen, Objekte und Klassen in verschiedene JavaScript-Dateien importieren und in einem einzigen Modul kombinieren. Der Weg zur Implementierung der Vererbung besteht darin, ein übergeordnetes Klassenmodul und ein untergeordnetes Klassenmodul zu erstellen und die Funktionen, Objekte und Klassen des übergeordneten Klassenmoduls im untergeordneten Klassenmodul zu verwenden. 🎜🎜Hier ist ein Beispiel für die Implementierung der geerbten Person-Klasse🎜rrreee🎜In diesem Beispiel haben wir ein Person-Modul und ein User-Modul, wobei letzteres vom ersteren erbt. Beachten Sie, dass wir require('./person') im Modul User verwendet, das Modul Person importiert und Extens Person verwendet haben erbt Benutzer von Person. Schließlich erstellen wir ein User-Objekt und versuchen, die Methode greet aufzurufen. Das Ergebnis war dieses Mal kein Problem. 🎜🎜🎜Verwenden Sie ES6 Proxy🎜🎜🎜 Eine andere Möglichkeit, das Problem in Node.js zu lösen, ist die Verwendung von ES6 Proxy. Proxy ist eine neue Funktion in JavaScript, die es uns ermöglicht, Hook-Funktionen für Objekte oder Funktionen auszuführen und deren Verhalten basierend auf unseren Anforderungen zu ändern. 🎜🎜Hier ist ein Beispiel: 🎜
class Person {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log(`Hello, my name is ${this.name}.`);
  }
}

class User extends Person {
  constructor(name, email) {
    super(name);
    this.email = email;
    this.proxy = new Proxy(this, {
      get(target, propKey) {
        return target[propKey] || target.__proto__[propKey];
      },
    });
  }

  static log(email) {
    console.log(`User ${email} logged in.`);
  }

  login() {
    User.log(this.email);
    this.proxy.greet();
  }
}

const user = new User('Tom', 'tom@example.com');
user.login();

在这个例子中,我们使用了一个新的属性 this.proxy。该属性是使用 new Proxy() 创建一个新的 Proxy 实例,该实例包装了当前的对象。 我们在 get 钩子函数中进行了一些重点的操纵,当我们通过 this.proxy.greet() 调用 greet 方法时,它会在当前对象上执行搜索不到,然后自动查找其原型,并在原型上找到该方法。

三、总结

继承是面向对象编程中的一个重要特性。然而,在 Node.js 的环境中,由于其异步性和 JavaScript 本身的面向对象编程模型,继承并不像在传统面向对象语言中那样简单直观。但是,我们可以通过模块模式和 ES6 Proxy 等解决方案来实现继承,以实现更完整的面向对象编程体验。无论使用哪种方案,重要的是确保我们在开发过程中遵循最佳实践,以确保代码的可维护性和稳健性。

Das obige ist der detaillierte Inhalt vonWarum Nodejs nicht erben können. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn