アップデート
この質問をしたので、たくさんの水が川の下に流れ込みました。モジュールパターンとCommonJSファイル形式+ Browserifyを使用するように切り替え、JavascriptをOOP言語に近づけることをやめました。私はJavascriptPrototypalInheritanceを採用しましたが、Object.create
私の人生はこれまで以上に良くなりました!はい、ほとんどJSに参加したような気がしますnew Religion
、申し訳ありませんがreligion
...もう「新しい」ものではありません。
残りの質問はただの歴史です...
私はしばらくの間、JavaScriptでOOPをいじっています。
正直なところ、私が感じているのは、ほとんどの場合、真のOOPは必要ないということです。私がOOPを使用して他の言語で行っていたことは、ほとんどの場合、JavaScriptの関数とクロージャを使用して行うことができました。
また、OOPアプローチを模倣するために、手作業で作成するか、そこにある小さなライブラリを使用して、OOPアプローチを有効にする方法がたくさんあります。
OOPを試してみたかったのですが、見つけたすべてのソリューションはそれほど単純ではないように見えました。initメソッドを追加するように要求されたり、初期化中に関数の特別な検査を行って、関数が必要かどうかを確認したりしていました。オーバーライド。それは賢いことですが、クラスからオブジェクトを単純に作成するには少し過剰に思えました。
だから私はこの解決策を思いついた:
更新:これは実験であり、既存の優れたライブラリを置き換えることや、本番環境で使用することを目的としたものではありません。
var Nexus = function() {}; // helper function to avoid create an instance of the child class
Object._extend = function(child, parent) {
var base = Nexus.prototype = parent.prototype;
child.prototype = new Nexus();
var cp = child.prototype;
cp.constructor = child;
child._parent = base;
};
/* THIS THEN IS USED LIKE THIS */
var Person = function (name) {
this.name = name;
console.log('Person constructor');
};
$.extend(Person.prototype, {
walk : function () {
console.log(this.name + ' is Walking!!');
}
});
var Student = function () {
// call the base class constructor
Student._parent.constructor.apply(this, arguments);
console.log('Student Constructor');
}
Object._extend(Student, Person);
$.extend(Student.prototype, {
walk : function () {
console.log(this.name + ' walks like Student');
//calling a parent method
Student._parent.walk.apply(this, arguments);
}
});
var p = new Person('Jon Doe');
p.walk();
console.log(p instanceof Person) // true
var s = new Student('Joan Doe');
s.walk();
console.log(s instanceof Person) // true
console.log(s instanceof Student) // true
ご覧のとおり、このアプローチはOOPが要求するものを満たしています。
- 子オブジェクトは、親クラスのインスタンスであると同時に、子クラスのインスタンスでもあります。
子objは、親クラスのメソッドを呼び出して、オーバーライドされたメソッドにアクセスできます。(CurrentClass._parentおよびBaseClass.prototypeとの唯一の違いは、2番目のものでは、クラスのコンシューマーが実際に親クラスの名前を知っている必要があることです。これは避けたかったのです)。
コンストラクターの作成は単純である必要がありました。この場合は...関数自体がコンストラクターです。インスタンス化中に自動的に呼び出される単純なinitメソッドは必要ありません。
私が従ったアプローチの短所:
- ダミークラスのNexusが必要です(継承チェーンを正しく機能させるためだけに基本クラスのオブジェクトをインスタンス化するのは好きではありません... Nexusがトリックを実行します)
- コンテキストが適切に設定されているオーバーライドされたメソッドへのアクセスを提供しませんでした。呼び出しまたは適用のいずれかを使用してコンテキストを変更するのは、コンシューマーの責任です。
適切なプロトタイプチェーンを作成するための追加のNexusダミー機能があることは、メモリ管理の問題ですか?
私は適切なテストを行う時間がありませんでした、そして私の継承チェーンは3レベルより深くありません。したがって、そこへの影響は非常に小さいようです。
そのためにライブラリを使用することもできましたが、ライブラリを直接作成し、コンストラクターにコードを配置することは非常に簡単で、初期化用に追加のinitクラスを使用することの利点を理解できませんでした。
ダミーのNexus機能を追加すると、目立った影響は何だと思いますか?