私はrequest
モジュールのコンポジットを構築していますが、JS for Nodeでオブジェクトを構築する際のベストプラクティスは何かわかりません。
オプション1:
function RequestComposite(request) {
return {
get: function (url) { return request.get(url); }
}
}
var comp = RequestComposite(request);
オプション2:
function RequestComposite(request) {
this.request = request;
}
RequestComposite.prototype.get = function (url) { return this.request.get(url); };
var comp = new RequestComposite(request);
オプション3:
var RequestComposite = {
init: function (request) { this.request = request; },
get: function (url) { return request.get(url); }
}
var comp = Object.create(RequestComposite).init(request);
私は自分の道を見つけようとしましたが、オブジェクトの使用方法についてさらに混乱しました...
ブラウザーにオブジェクトを使用したい場合、答えは異なりますか?
ありがとう。
最も効率的な方法は次のとおりです。
コンストラクターでプロパティのみを設定します。
コンストラクターの.prototype
プロパティでメソッドを設定します。どうして?これは、オブジェクトを作成するたびに各メソッドを書き直すことを防ぐためです。このようにして、作成する各オブジェクトに対して同じプロトタイプをリサイクルします。メモリと時間の効率的。
プライベートプロパティにクロージャーを使用しないでください。なぜですか?:遅いため、このオブジェクトを継承チェーンで使用できません(疑似プライベート変数はオブジェクトに属しておらず、単にアクセス可能です)。代わりにアンダースコアを使用して、外部からアクセスすべきではないプライベートプロパティであることを示します。
Object.create
の代わりにnew
を使用します。より高速で、最後にObject.createは内部でnew
を使用します。
つまり、次のようなものです。
var Person = function (name) {
this._name = name;
};
Person.prototype.sayHello = function () {
alert('My name is: ' + this._name);
};
var john = new Person('John');
john.sayHello();
いくつかの追加情報:
Object.create vs new。 ここにベンチマーク 。質問はnode.jsに対するものですが、同じ動作が予想されると思います。 (修正は大歓迎です)
プライベートプロパティをエミュレートするクロージャー: この質問 について読むことができます。プライベート/クロージャープロパティがオブジェクトに属さないという点は、プログラミングの事実です。これらは、オブジェクトメソッドによってアクセス可能ですが、オブジェクトには属しません。継承を使用する場合、それは大きな混乱です。また、コンストラクターで宣言されているメソッドのみがクロージャーにアクセスできます。プロトタイプで定義されたメソッドはそうではありません。
コンストラクタまたはプロトタイプのプロパティでメソッドを定義する: この質問 を読み、 このベンチマークを見てください
3年前にここで行ったポイントは、パフォーマンスの観点からはまだ正しいですが、「推奨される方法」とは何かについての私の意見は、その間に少し変わっています。ファクトリ関数は一般に良いオプションであり、OPの最初のアプローチです。ほんの一例:
function Person(name) {
return {
sayHello: function () { alert('My name is: ' + name); }
};
}
そして、ただやる:
var p = Person('John');
この場合、柔軟性(new
カップリングなし、他の「ミックスイン」との構成の容易さ)および単純さ(this
混乱なし、オブジェクトのインスタンス化の容易さ)をある程度の速度とメモリーと引き換えます。一般に、それらは完全に有効です。パフォーマンスの問題があり、その原因がオブジェクトの作成方法である場合は、別の方法に戻ります。 Object.create
アプローチも優れており、何らかの理由でnew
とファクトリー関数の中間に位置します(注:新しいclass
構文は、new
+ prototype
の構文シュガーです)
要約:私の推奨する方法は、オブジェクト(ファクトリー関数)を作成する最も簡単で最も簡単な方法から始め、パフォーマンスの問題(ほとんどの場合は決してない)になったときに他の方法に移ります。
JSで「クラス」と「オブジェクト」を作成する方法はたくさんあります。私はこの方法を好む:
var MyObject =
function(args) {
// Private
var help = "/php/index.php?method=getHelp";
var schedule = "/php/index.php?method=getSchedules";
var ajax = function(url, callback, type) {
//....
}
// Public
this.property = 0;
this.getInfo = function() {
// ...
}
// Constructor
function(data) {
this.property = data;
}(args);
};
var o = new MyObject();
注:OOP構文に精通している場合は、 class
を使用することもできます。これは、既存のプロトタイプベースの方法よりも単なる構文上の砂糖です。
オブジェクトを作成する4つの方法のパフォーマンス比較-コンストラクターを使用して(Chrome 61- https://jsperf.com/create-object-ways )
オプションA:return
の使用(最速3x)
オプションB:{key:value}
の使用(1.5x)
オプションC:prototype
(1x)<-Baseの使用
オプションD:class
の使用(1.02x)
オプションA最高のパフォーマンスを得るための縫い目。パフォーマンスの向上の一部は、new
またはobject.create
の使用を避けるためです。公正な試用のために、コンストラクタとプロパティのないメソッドのみのオブジェクト間の別のテストを示します。
メソッドのみのオブジェクトを作成する4つの方法のパフォーマンス比較(Chrome 61- https://jsperf.com/create-static-object -ways )
オプションA:return
の使用(3.2x)
オプションB:{key:value}
の使用(最速3.3x)
オプションC:prototype
の使用(1.8x)
オプションD:class
の使用(1.9x)
オプションBを上回りましたオプションAを少し上回りました。また、object.create
によって引き起こされるボトルネックは、new
を超えていました。
ベストプラクティス
オプションA(return
を使用)は、両方のシナリオで最高のパフォーマンスを発揮します。多くのメソッドとプロパティがある場合、この方法は少し面倒になります。
Option Aを使用して別のオブジェクトのコンストラクターとプロパティを分割し、Option B。このアプローチでは、パラメーターで追加のinstance
参照を送信する必要がありますが、同じプロパティとコンストラクターを使用する複数のオブジェクトがある場合に役立ちます(一部のOOP継承も実現可能)。
例:
// Constructor & Properties Object (Using option A)
var UserData = function(request){
// Constructor
if ( request.name )
var name = request.name;
else
var name = 'Not Available';
if ( request.age )
var age = request.age;
else
var age = null;
// Return properties
return {
userName: name,
userAge: age
};
};
// Object methods (Using Option B)
var Adults = {
printName: function(instance){ // Read propery example
console.log( 'Mr. ' + instance.userName );
},
changeName: function(instance, newName){ // Write property example
instance.userName = newName;
},
foo: function(){
console.log( 'foo' );
}
};
// Object methods (Using Option B)
var Children = {
printName: function(instance){
console.log( 'Master ' + instance.userName );
},
bar: function(){
console.log( 'bar' );
}
}
// Initialize
var userData = UserData ( {name: 'Doe', age: 40} );
// Call methods
Adults.printName(userData); // Output 'Mr. Doe'
Children.printName(userData); // Output 'Master Doe'
Adults.foo(); // Output 'foo'
Children.bar(); // Output 'bar'
Adults.changeName(userData, 'John');
Adults.printName(userData); // Output 'Mr. John'