30

JavaScriptでオブジェクトをインスタンス化するいくつかの異なる方法を見てきました.さまざまなアプローチの利点/欠点と、なぜそれらを使用するのかを知りたい.

アプローチ1

var obj = {
    prop: value,
    .
    .
    .
}

アプローチ1は標準的なアプローチであり、新しいものではありません:)

アプローチ 2

var obj = new function() {
    var prop1 = value1;
    var fn1 = function() {
    };
    .
    .
    .

    this.prop2 = value2;
    .
    .
    .
}();

関数アプローチ、このアプローチをアプローチ 3 と比較したかったのです。関数アプローチは主にカプセル化に使用されます (正しいですか?)

アプローチ 3

var obj = (function() {
    var prop1 = value1;
    var fn1 = function() {
    };
    .
    .
    .

    return {
        prop2: value2,
        .
        .
        .
    }
})();

このアプローチでは、その使用の背後にある理由がよくわかりません。アプローチ 2 との違いは何ですか? どちらもロジックをカプセル化するために使用できます。

パラメータを渡すことができるので、潜在的な競合に対処できますか?? たとえば、jquery の$構文 - ただし、アプローチ 2 でこれを行うこともできます...

ありがとう。


編集:


アプローチ 1 と 3 は (両方ともオブジェクトを返すという点で) 似ていることは承知していますが、アプローチ 3 もクロージャーを作成します。どのアプローチ2も行います。

それが私の質問の基本です.2と3の両方がクロージャーを作成しますが、それらの違いは何ですか.

4

9 に答える 9

27

JavaScript でオブジェクトを作成する 7 つの方法:

1. オブジェクトコンストラクター

オブジェクトを作成する最も簡単な方法は、Object コンストラクターを使用することです。

var person = new Object();  
person.name = "Diego";  
person.getName = function(){  
    return this.name;  
}; 

2. リテラル表記

プレーンプリントを表示しますか?

var person = {  
    person.name : "Diego",  
    person.getName : function(){  
        return this.name;  
    }  
} 

3. 工場機能

Factory 関数を使用すると、同様のオブジェクトを作成するためのロジックをカプセル化して再利用できます。これには、以前の構造のいずれかが利用されます。どちらか:プレーンプリントを表示しますか?

var newPerson=function(name){  
    var result = new Object();  
    result.name = name;  
    result.getName = function(){  
        return this.name;  
    };  
    return result;  
};  
var personOne = newPerson("Diego");  
var personTwo = newPerson("Gangelo");  
console.log(personOne.getName()); // prints Diego  
console.log(personTwo.getName()); // prints Gangelo

または:

view plainprint?
var newPerson=function(name){  
    return {  
        person.name : name,  
        person.getName : function(){  
            return this.name;  
        };  
};  
var personOne = newPerson("Diego");  
var personTwo = newPerson("Gangelo");  
console.log(personOne.getName()); // prints Diego  
console.log(personTwo.getName()); // prints Gangelo  

4. 関数コンストラクター

Javascript では、関数の前に new 演算子を付けて任意の関数を呼び出すことができます。関数 F が与えられると、new F() に対して: 新しい空のオブジェクト X が作成されます。X は F のコンテキストとして設定され、F 全体でこれが X を指すことを意味します。X は F ビューのプレーンプリントの結果として返されますか?

function Person(name){  
        this.name = name;  
        this.getName = function(){  
            return this.name;  
        };  
};  
var personOne = new Person("Diego");  
console.log(personOne.getName()); // prints Diego  
console.log(personOne instanceOf Person); // prints true  
console.log(personOne.constructor === Person); // prints true  
console.log(personOne instanceOf Object); // prints true  

5. プロトタイプ

Functions are very special in Javascript. They are objects, they can create other objects and they automatically get a field called prototype. A prototype is a plain object with a single field, called constructor, pointing to the function itself. What makes it special is that every object created through a function inherits the function's prototype. view plainprint?

function Person(){};  
Person.prototype.name = "Diego";  
var personOne = new Person();  
var personTwo = new Person();  
console.log(personOne.constructor == Person); // prints true  
console.log(personOne.name); // prints Diego  
console.log(personTwo.constructor == Person); // prints true  
console.log(personTwo.name); // prints Diego  

6. Function/Prototype combination

The function/prototype combination, as you would imagine, takes advantage of both approaches :) view plainprint?

function Person(name){  
        this.name = name;  
};  
Person.prototype.getName = function(){  
            return this.name;  
        };  
var personOne = new Person("Diego");  
var personTwo = new Person("Filippo");  
console.log(personOne.getName()); // prints Diego  
console.log(personTwo.getName()); // prints Filippo  
console.log(personOne.getName === personTwo.getName) //prints true 

7. Singleton

Sometimes, you may want to make sure that only a single instance of a certain class exists. To get a Singleton in Javascript is as simple as defining and invoking the constructor at the same time: view plainprint?

var singleton = new function(){  
    this.name = "ApplicationName";  
};  
于 2014-12-10T09:48:59.467 に答える
4

Object1 番目と 3 番目のアプローチはほとんど同じで、クラスの直接の子であるオブジェクト リテラルを作成します。それらの違いは、3 番目のアプローチでは、ある種のプロパティのカプセル化がある場合があることです。

var obj = (function() {
    var prop = {};

    return {
        prop2: function(){ return prop };
    }
})();

パフォーマンスに関しては、3 番目のアプローチは閉鎖を作成しますが、最初のアプローチはそうではないと考えるかもしれません。

ただし、2 番目のアプローチでは、クラスの直接の子ではない匿名クラスから新しいオブジェクトを作成するだけですObject

2 番目のアプローチの正しい形式は次のとおりです (少なくとも ecma 標準です)。

var obj = new function() {
    var prop1 = value1;

    this.prop2 = value2;
}();

アプローチ 2 と 3 の違いは、継承チェーンのみです (obj2 が 2 番目のアプローチからのもので、obj3 が 3 番目のアプローチからのものであると仮定します)。

obj2.__proto__ == Object.prototype;  // false
obj3.__proto__ == Object.prototype;  // true

obj2 は匿名クラス自体から作成されます。

obj2.__proto__.__proto__ == Object.prototype;  // true (there's 2 level of inheritance here)
于 2013-04-19T16:26:25.550 に答える
3

次のものもあります。

var obj = Object.create({prop: ...});

これは、プロトタイプを設定することで機能します。複数のオブジェクトでプロパティやメソッドを共有する場合は、プロトタイプを使用する方がはるかに効率的です。

var proto = {foo: function() {}},
    obj1 = Object.create(proto),
    obj2 = Object.create(proto),
    obj3 = {foo: function() {}},
    obj4 = {foo: function() {}};

この例では、obj1 と obj2 は「proto」で定義された「foo」関数を共有しています。一方、obj3 と obj4 にはそれぞれ独自の「foo」があります。多数のプロパティを持つ多数のオブジェクトを作成している場合、これによりメモリ消費やパフォーマンスに大きな違いが生じる可能性があります。

この利点は、名前付き関数を使用し、new を使用する前に関数のプロトタイプ (例: f.prototype.prop) にプロパティを割り当てる場合、「new」キーワードを使用することによって共有されます。

于 2013-12-09T08:25:38.490 に答える
0

アプローチ 2 を理解するために、読者は新しいキーワードの仕組みについて非常に技術的なことを知る必要があります。具体的には、新しい関数オブジェクトをインスタンス化して obj 変数にダンプするのではなく、実際に無名関数をコンストラクターとして呼び出します。

アプローチ 3 を理解するには、IIFE パターンを理解する必要があります。過去 2 年間で、このパターンは JavaScript コードで非常に一般的になりました。そのため、おそらくそのバージョンがより一般的に使用されています。

どちらのバージョンもカプセル化を生成するために使用され、両方のバージョンを理解するには複雑な言語機能の知識が必要です。ただし、アプローチ 3 で必要な言語機能は、アプローチ 2 を理解するために必要な言語機能よりも一般的に知られています。これが、アプローチ 3 が実際によく使用される理由です。

于 2013-04-19T16:33:00.000 に答える
0

1 回限りのオブジェクトの場合、アプローチ 2 と 3 の間に大きな違いはありません。(アプローチ 2 で使用される関数に名前を付けるとしたら、再利用可能なコンストラクターを定義したことになります。) 私の印象では、これらの状況ではアプローチ 3 がより一般的に使用されますが、それらの間に大きな違いは見られません。

アプローチ 2 と 3 の両方が引数を取ることができることに注意してください。

var approach2Obj = new function(formalArg) {
    var privateProp = ...;
    this.publicProp = ...;
    // more constructor logic
)(actualArg);

var approach3Obj = (function(formalArg) {
    var privateProp = ...;
    // more creation logic
    return {
        publicProp : ...;
    };
}(actualArg));

PS @Alexey Lebedevが彼の答えで指摘しているように、2つの違いの1つ(おそらく唯一のもの)はそれでapproach2Obj.constructorあり、approach3Obj.constructor異なるでしょう。approach3Obj.constructorは同一Objectapproach2Obj.constructorなりますが、無名関数になります。

于 2013-04-19T16:24:17.830 に答える