2011-02-01 18 views
78

JavaScriptを使ってオブジェクトを作成する方法を混乱させています。少なくとも2つの方法があるようです。 1つはオブジェクトリテラル表記を使用し、もう1つは構築関数を使用することです。 1つの利点は他のものよりも優れていますか?オブジェクトリテラルまたはコンストラクタ関数を使用する必要がありますか?

+1

ベスト・アンサー:http://stackoverflow.com/questions/4597926/creating-objects-new-object-or-object-literal-notation - インスタンスを作成するための関数を設定することができますリテラル記法も同様に作成します。これを行うたびにすべてのメソッドが実行されますが、コンストラクタではすべてのインスタンスがプロトタイプメソッドを参照します。つまり、コンストラクタはメモリのパフォーマンスが優れています。 – Federico

答えて

106

オブジェクトに関連する動作がない場合(つまり、オブジェクトがデータ/状態の単なるコンテナである場合)、オブジェクトリテラルを使用します。

var data = { 
    foo: 42, 
    bar: 43 
}; 

KISS principleを適用してください。単純なデータのコンテナ以外のものが必要ない場合は、単純なリテラルを使用してください。

オブジェクトにビヘイビアを追加する場合は、コンストラクタにアクセスして、作成中にオブジェクトにメソッドを追加するか、クラスにプロトタイプを渡すことができます。

function MyData(foo, bar) { 
    this.foo = foo; 
    this.bar = bar; 

    this.verify = function() { 
     return this.foo === this.bar; 
    }; 
} 

// or: 
MyData.prototype.verify = function() { 
    return this.foo === this.bar; 
}; 

このようなクラスはまた、あなたのデータオブジェクトのスキーマのような役割を果たし:あなたは今(コンストラクタによる)契約のいくつかの並べ替えを持っているオブジェクトが含まれている/初期化をどのような特性。フリーのリテラルは、データのアモルファスな塊です。

あなたにも、昔ながらのデータオブジェクトに作用する外部verify機能かもしれません。しかし

var data = { 
    foo: 42, 
    bar: 43 
}; 

function verify(data) { 
    return data.foo === data.bar; 
} 

を、これはカプセル化に関して有利ではありません。理想的には、関連付けられているすべてのデータ+行動エンティティは一緒に生きるべきです。

+7

大きな説明、 – chobo

+20

オブジェクトリテラルの一部として関数定義を含めるか、 'this.fn =関数を使用する場合は、次のようにしますプロジェクトのアプローチを使用すると、各関数をプロトタイプの継承を通じてインスタンスに継承されます。 –

+11

Iあなたが重要なことを逃したと思っています。コンストラクタ関数だけが、プライベートメンバとパブリックメンバ(カプセル化)をオブジェクトリテラルに提供することができます - それらはすべてpublicです。 –

0

オブジェクトリテラルを使用すると、初期値の導入によってより合理的になります。

+0

オブジェクトリテラルにプライベート変数を作成するにはどうすればよいですか? – EhevuTov

+0

本当に元の質問とは関係ないので、私はちょうどあなたにリンクを与えるつもりです:http://javascript.crockford.com/private.html – Tom

+1

実際には、特定の状況に応じてどちらか一方を使用する理由があります。この例では、プライベート変数を使用するかどうかを指定します。最初にリテラルにクロージャー関数を作成することで、リテラルにプライベート変数を作成できますが、それは私の意見では非常に醜いので、読みにくいです。 – EhevuTov

5

あなたのやりたいことによって異なります。オブジェクト内で(半)プライベート変数または関数を使用する場合は、コンストラクタ関数を使用します。オブジェクトにプロパティとメソッドのみが含まれている場合、オブジェクトリテラルは問題ありません。

function SomeConstructor(){ 
    var x = 5; 
    this.multiply5 = function(i){ 
     return x*i; 
    } 
} 
var myObj = new SomeConstructor; 

var SomeLiteral = { 
    multiply5: function(i){ return i*5; } 
} 

今方法myObjmultiply5SomeLiteralはまったく同じことを行います。唯一の違いは、myObjがプライベート変数を使用することです。後者は場合によっては有用かもしれない。ほとんどの場合、Objectリテラルで十分であり、JSオブジェクトを作成するためのきれいでクリーンな方法です。

+0

関数とメソッドの違いは何ですか?私はC#のバックグラウンドから来ているので、私には関数はスタンドアローンであり、メソッドはクラスの一部である関数に過ぎません。 – chobo

+1

それほど大きな違いはありません。たとえばhttp://www.web-source.net/javascript_tutorial/javascript_functions_methods.htmを参照してください。実際には、DOMscripting(ブラウザのクライアント側のjs)では、すべての関数がwindow-object(グローバル名前空間)のメソッドになります(すべての 'スタンドアロン'関数をウィンドウとして扱うことができます)[somefunction]。 – KooiInc

81

オブジェクトの複数のインスタンスを必要とするかどうかは、本質的に沸騰します。コンストラクタで定義されたオブジェクトは、そのオブジェクトの複数のインスタンスを持つことができます。オブジェクトリテラルは、基本的にすべてがパブリックな変数/メソッドを持つシングルトンです。 JavaScriptでの関数は、私たちがプライベート変数やメソッドを使用してnewを回避することができますクロージャですので

function makeObject() { 
    var that = { 
     thisIsPublic: "a public variable" 
     thisIsAlsoPublic: function() { 
      alert(that.thisIsPublic); 
     } 
    }; 

    var secret = "this is a private variable" 

    function secretFunction() { // private method 
     secret += "!"; // can manipulate private variables 
     that.thisIsPublic = "foo";  
    } 

    that.publicMethod = function() { 
     secret += "?"; // this method can also mess with private variables 
    } 

    that.anotherPublicVariable = "baz"; 

    return that; // this is the object we've constructed 
} 

makeObject.static = "This can be used to add a static varaible/method"; 

var bar = makeObject(); 
bar.publicMethod(); // ok 
alert(bar.thisIsPublic); // ok 
bar.secretFunction(); // error! 
bar.secret // error! 

:統一された方法でオブジェクトを作成するための

// define the objects: 
var objLit = { 
    x: 0, 
    y: 0, 
    z: 0, 
    add: function() { 
    return this.x + this.y + this.z; 
    } 
}; 

var ObjCon = function(_x, _y, _z) { 
    var x = _x; // private 
    var y = _y; // private 
    this.z = _z; // public 
    this.add = function() { 
    return x + y + this.z; // note x, y doesn't need this. 
    }; 
}; 

// use the objects: 
objLit.x = 3; 
objLit.y = 2; 
objLit.z = 1; 
console.log(objLit.add());  

var objConIntance = new ObjCon(5,4,3); // instantiate an objCon 
console.log(objConIntance.add()); 
console.log((new ObjCon(7,8,9)).add()); // another instance of objCon 
console.log(objConIntance.add()); // same result, not affected by previous line 
+1

これは、決定する際に留意すべき点です。どうも。 – zkent

+0

私の経験上、これはまさに違いを生むものです。非常に明確な例。 – Air

+0

gr8説明...非常に有益な情報 – Vikash

5

以下のコードは、オブジェクト、オブジェクトリテラル構文、関数コンストラクター、およびObject.create()の3つの作成方法を示しています。オブジェクトのリテラル構文は、即座に作成してオブジェクトにするだけで、__prototype__Objectオブジェクトであり、Objectのすべてのプロパティとメソッドにアクセスできます。厳密には、デザインパターンの観点から、単純なObjectリテラルを使用してデータの単一のインスタンスを格納する必要があります。

ファンクションコンストラクタには、.prototypeという特別なプロパティがあります。このプロパティは、関数コンストラクタによって作成されたオブジェクトの__prototype__になります。関数コンストラクタの.prototypeプロパティに追加されたすべてのプロパティとメソッドは、作成するすべてのオブジェクトで使用できます。データの複数のインスタンスが必要な場合や、オブジェクトからの動作が必要な場合は、コンストラクタを使用する必要があります。関数コンストラクタは、プライベート/パブリックの開発パターンをシミュレートする場合にも最適です。すべての共有メソッドを.prototypeに置くことを忘れないでください。そうすれば、それぞれのオブジェクトインスタンスで作成されることはありません。

Object.create()でオブジェクトを作成すると、このメソッドで作成されたオブジェクトのオブジェクトリテラルが__prototype__として利用されます。オブジェクトリテラルに追加されたすべてのプロパティとメソッドは、実際のプロトタイプ継承によって作成されたすべてのオブジェクトで使用できます。これが私の好ましい方法です。

//Object Example 

//Simple Object Literal 
var mySimpleObj = { 
    prop1 : "value", 
    prop2 : "value" 
} 

// Function Constructor 
function PersonObjConstr() { 
    var privateProp = "this is private"; 
    this.firstname = "John"; 
    this.lastname = "Doe"; 
} 
PersonObjConstr.prototype.greetFullName = function() { 
    return "PersonObjConstr says: Hello " + this.firstname + 
    " " + this.lastname; 
}; 

// Object Literal 
var personObjLit = { 
    firstname : "John", 
    lastname: "Doe", 
    greetFullName : function() { 
     return "personObjLit says: Hello " + this.firstname + 
     ", " + this.lastname; 
    } 
} 

var newVar = mySimpleObj.prop1; 
var newName = new PersonObjConstr(); 
var newName2 = Object.create(personObjLit); 
+0

あなたはオブジェクトリテラルの中で関数を宣言しています。これは、 'Object.create'を使ってオブジェクトを作成するときに、リテラル内の関数がインスタンスごとに一意であることを意味しますか? – JohnnyQ

-1

//コンストラクタオブジェクトリテラルとオブジェクト

function MyData(foo, bar) { 
     this.foo = foo; 
     this.bar = bar; 

    } 
MyData.prototype.verify = function() { 
     return this.foo === this.bar; 
    }; 

//add property using prototype 

var MD = new MyData;//true. 
var MD = new MyData();//true. 
MD.verify// return only the function structure. 
MD.verify(); //return the verify value and in this case return true coz both value is null. 
var MD1 = new MyData(1,2); // intialized the value at the starting. 
MD1.verify// return only the function structure. 
MD1.verify(); // return false coz both value are not same. 
MD1.verify(3,3);// return false coz this will not check this value intialized at the top 
MyData.prototype.verify = function (foo,bar) { 
    return this.foo === this.bar; 
}; 
var MD1 = new MyData(1,2); 
MD1.verify(); 
MD1.verify(3,3);// return false coz this keyword used with foo and bar that will check parent data 
+1

あなたの例でObjectリテラルが宣言されていますか? – JohnnyQ

2

enter image description here

ページのオブジェクトの単一のインスタンスをしたいですか - リテラルを。

あなたはDTOは、単純なGETのSETオブジェクトのように、単にデータを転送しますか: - コンストラクター機能、フォローOOPの原則、継承 - リテラル

はあなたが本当のメソッドの振る舞いを持つオブジェクト、複数のインスタンスを作成しますか: - コンストラクタ関数を。

以下は、リテラルとは何か、コンストラクタ関数とはどのように違うのかを詳しく説明するYouTubeのビデオです。

https://www.youtube.com/watch?v=dVoAq2D3n44

0

https://www.w3schools.com/js/js_object_definition.aspオブジェクトリテラルを使用して

で述べたように、あなたは両方のは 文で1つのオブジェクトをを定義し、を作成し、

また

オブジェクトリテラルのみ単一のオブジェクトを作成します。場合によっては 多くのオブジェクトを作成するために使用することができます。

関連する問題