web-dev-qa-db-ja.com

Javascript作成オブジェクト-複数のアプローチ、違いはありますか?

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

アプローチ1

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

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

アプローチ2

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

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

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

アプローチ

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

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

このアプローチでは、その使用法の背後にある理由がわかりません。アプローチ2との違いは何ですか?両方を使用してロジックをカプセル化できます。

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

ありがとう。


編集:


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

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

26
Umair

アプローチ#2と#3では、結果のオブジェクトのconstructorプロパティは異なります。

実際には、2番目のアプローチでは、匿名コンストラクター関数を使用して複数のオブジェクトをインスタンス化できます。

x = new function() { alert(1) };
y = new x.constructor; // shows the message too

モジュールコンストラクター対匿名コンストラクターのインスタンス の一番の答えには、ダグラスクロックフォードからの引用が含まれています。

10
Alexey Lebedev

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

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

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

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;  
    }  
} 

。ファクトリー関数

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が与えられ、新しいF()の場合:新しい空のオブジェクトXが作成されます。 XはFのコンテキストとして設定されます。これは、F全体でXを指すことを意味します。Xは、F view plainprintの結果として返されますか?

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。プロトタイプ

関数はJavascriptで非常に特別です。これらはオブジェクトであり、他のオブジェクトを作成でき、プロトタイプと呼ばれるフィールドを自動的に取得します。プロトタイプは、コンストラクターと呼ばれる、関数自体を指す単一のフィールドを持つ単純なオブジェクトです。特別なことは、関数を介して作成されたすべてのオブジェクトが関数のプロトタイプを継承することです。プレーンプリントを表示しますか?

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 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。シングルトン

特定のクラスのインスタンスが1つだけ存在することを確認したい場合があります。 Javascriptでシングルトンを取得するには、コンストラクターを同時に定義して呼び出すのと同じくらい簡単です。

var singleton = new function(){  
    this.name = "ApplicationName";  
};  
22

最初のアプローチと3番目のアプローチはほぼ同じです。両方ともObjectクラスの直接の子であるオブジェクトリテラルを作成する方法が異なります。それらの違いは、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)
4
Kamyar Nazeri

またあります:

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」キーワードの使用によって共有されます。

2
rich remer

アプローチ1
これは単一のオブジェクトであり、クラスはありません。複雑な場合、より簡単に定義することはできません

_var obj = {
   prop: value
}
_

アプローチ2
非匿名関数。 「クラス」からオブジェクトを作成します。通常、関数はクラス名として保存され、同じタイプの複数のオブジェクトを以下のように簡単に作成できます。

_var Bycicle= function() {
    var prop1 = value1;

    this.prop2 = value2;
}
var obj1 = new Bycicle(),
    obj2 = new Bycicle();
_

アプローチ3
匿名関数、関数外からの変数は、関数内の変数と干渉できません。

_var a = 10;
var obj = (function() {
    alert(a); // Alerts undefined
    var prop1 = value1;
    alert(prop1); // alerts the value of value1
    return {
        prop2: value2;
    }
})(); // Within the () you can pass arguments to the anonymous function.
_

匿名関数の詳細: http://helephant.com/2008/08/23/javascript-anonymous-functions/

その他のアプローチ
新しいオブジェクトを作成するObject.create()new Object()もあります。どちらもアプローチ1と同じです。

結論
最後に、オブジェクトは匿名であるため、3番目のオブジェクトを除いて常に同じになります。

2
Niels

私は少しJSと一緒に働いていて、いくつかの答えを投稿することを考えました、それが他の誰かにも役立つことを願っています:

1)Object Literal:作成中に文学を書き留めた

var person = {
  name: ['Bob', 'Smith'],
  age: 32,
  gender: 'male',
  interests: ['music', 'skiing'],
  bio: function() {
    alert(this.name[0] + ' ' + this.name[1] + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
  },
  greeting: function() {
    alert('Hi! I\'m ' + this.name[0] + '.');
  }
};

使用法:サーバーにデータを転送する場合

2)コンストラクター関数:同じ好みの複数のオブジェクトを作成する場合は、コンストラクター関数を使用します。

function Vehicle(name, maker) {
  this.name = name;// Every function while executing has a reference         
            this.maker = maker;// to its current execution context called as this
}
let car1 = new Vehicle(’Fiesta’, 'Ford’);// New keyword with function turns function call into constructor call
let car2 = new Vehicle(’Santa Fe’, 'Hyundai’);

console.log(car1.name);    //Output: Fiesta
console.log(car2.name);    //Output: Santa Fe

3)createメソッドでJavascriptオブジェクトを作成

Object.create()は、value、configurable、enumerableおよびwritableなどの属性オプションを使用してオブジェクトを作成できます。パラメーターとして渡されたプロトタイプオブジェクトを拡張する新しいオブジェクトを作成します

let car = Object.create(Object.prototype,{
   name:{
     value: 'Fiesta',
     configurable: true,
     writable: true,
     enumerable: false
   },
   maker:{
     value: 'Ford',
     configurable: true,
     writable: true,
     enumerable: true
   }});
console.log(car.name)    //Output: Fiesta

プロトタイプ:すべての単一オブジェクトは、コンストラクター関数によって構築されます。コンストラクター関数は、オブジェクトを独自のプロトタイプにリンクさせますプロトタイプは、コンストラクターとオブジェクト間の任意のリンクです。

4)ES6クラスを使用してJavascriptを作成します

class Vehicle {
 constructor(name, maker, engine) {
   this.name = name;
   this.maker =  maker;
   this.engine = engine;
 }
}

let bike1 = new Vehicle('Hayabusa', 'Suzuki', '1340cc');
let bike2 = new Vehicle('Ninja', 'Kawasaki', '998cc');

console.log(bike1.name);    //Output: Hayabusa
console.log(bike2.maker);   //Output: Kawasaki

5)オブジェクトコンストラクターの使用

var d = new Object();

空のオブジェクトを作成する最良の方法。

注:このリンクのほとんどのコンテンツをコンパイルしました https://codeburst.io/various-ways-to-create-javascript-object-9563c6887a47

1
Apurva Pathak

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

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

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

0
Racheet

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));

追伸 @ Alexey Lebedevが答えで指摘している のように、2つ(おそらく唯一のもの)の違いはapproach2Obj.constructorおよびapproach3Obj.constructorは異なります。 approach3Obj.constructorObjectと同じですが、approach2Obj.constructorは匿名関数になります。

0
Ted Hopp

ApproachApproach 1とまったく同じであるため、あなたの質問は2つのアプローチである必要があります。

Approach 1のようなオブジェクトを作成する場合の違いについては、Javaのような静的関数のみを持つオブジェクトのように考えることができます。そのため、常に生きており、インスタンスを作成しません(シングルトンに似ています)-このオブジェクトを作成すると:

var obj = {
    prop: value,
    func: function(){
     alert(this.prop);
    }
};

すぐに呼び出すことができます:

obj.prop = 'something else';
obj.func();

アプローチ2(あなたが持っているコメントのような新しいものなし)は、インスタンスを作成できる古典的なオブジェクトです-継承(js "トリック"を使用)など:

function Person(firstName,lastName){ // or var Person = function(...
   this.firstName = firstName;
   this.lastName= lastName;

   this.getFullName = function(){
      return this.firstName + ' ' + this.lastName;
   }
}

//use
var person1 = new Person('yair','lapid');
var person2 = new Person('Naftali','Bennet');

you can put it in an array etc...
var arr = [person1,person2, new Person('shelly','yekimovits')];
0
Adidi