近年、Node.js (以下、Node) は、世界で最も人気のあるサーバーサイド JavaScript プラットフォームの 1 つになりました。 Node には、実行速度、メモリ使用量、サポートされているライブラリやフレームワークなど、多くの機能がありますが、いくつかの側面では依然として独自の制限があります。最も顕著な問題の 1 つは、Node.js を継承できないことです。
オブジェクト指向プログラミングでは、継承は開発者が基本クラス (親クラス) を作成し、それに基づいて他のサブクラスを作成できるようにする重要な機能です。これらのサブクラスは、親クラスのメソッドをオーバーライドしたり、新しいメソッドを追加して機能を拡張および再利用したりできます。 Node.js のコンテキストでは、継承は通常、クラス間でプロパティとメソッドをコピーする形式をとります。ただし、Node.js の非同期モデルと JavaScript の柔軟性との相互作用により、Node では継承があまり直感的ではなく、実装が難しい場合があります。この記事では、Node.js が継承できない理由といくつかの代替案について説明します。
1. Node.js での継承の実装の問題
Node.js での継承の問題を認識するには 2 つの重要な要素があります:
Node.js の機能の 1 つは、JavaScript と密接に関係している非同期プログラミング モデルです。 Node.js はシングルスレッドであるため、複数のクライアント要求やその他の非同期タスクを処理するには、非同期モデルを使用する必要があります。非同期モデルは Node.js の効率を高めますが、継承された実装と競合します。非同期プログラミングでは、関数呼び出しはタイマーに基づいて行われるためです。非同期関数を呼び出した後、プログラムは実行を継続し、非同期コールバックが完了するまで関数には戻りません。
次のコード部分を考えてみましょう:
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();
この例には、クラス Person
と、# を継承する別のクラス User
があります。 ##人###。 User
インスタンスで login
メソッドを呼び出すときは、まず User
クラスに固有の log
メソッドを呼び出し、次に親クラスの greet
メソッドを呼び出します。ただし、関数は非同期で実行されるため、結果は期待どおりにはなりません。<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">User alice@example.com logged in.
undefined</pre><div class="contentsignin">ログイン後にコピー</div></div>
実際、呼び出し順序は間違っています。
は非同期動作に基づいて呼び出されるため、このメソッドの実行は、非同期 User.log
メソッドのコールバックの後に実行されます。そのため、画面には 未定義
が表示されます。
プロトタイプベースの継承モデルでは、開発者は
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.constructor
関数呼び出しを通じてユーザーを登録します。 2. 解決策
Node.js にはいくつかの制限がありますが、継承された機能を実現するための解決策がいくつかあります。ここでは、一般的なソリューションをいくつか紹介します。
モジュールベースの継承これは 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 Person
を使用したことに注意してください。 User
を 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();
在这个例子中,我们使用了一个新的属性 this.proxy
。该属性是使用 new Proxy()
创建一个新的 Proxy 实例,该实例包装了当前的对象。 我们在 get 钩子函数中进行了一些重点的操纵,当我们通过 this.proxy.greet()
调用 greet
方法时,它会在当前对象上执行搜索不到,然后自动查找其原型,并在原型上找到该方法。
三、总结
继承是面向对象编程中的一个重要特性。然而,在 Node.js 的环境中,由于其异步性和 JavaScript 本身的面向对象编程模型,继承并不像在传统面向对象语言中那样简单直观。但是,我们可以通过模块模式和 ES6 Proxy 等解决方案来实现继承,以实现更完整的面向对象编程体验。无论使用哪种方案,重要的是确保我们在开发过程中遵循最佳实践,以确保代码的可维护性和稳健性。
以上がなぜnodejsは継承できないのかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。