オブジェクトリテラルまたはコンストラクター関数を使用する必要がありますか?


94

JavaScriptでオブジェクトを作成する方法について、混乱しています。少なくとも2つの方法があるようです。1つはオブジェクトリテラル表記を使用する方法で、もう1つは構築関数を使用する方法です。どちらか一方の利点はありますか?


1
最良の答え:stackoverflow.com/questions/4597926/…-要約すると、リテラル表記からインスタンスを作成する関数も設定できます。これを行うと、インスタンスごとにすべてのメソッドが実行されますが、コンストラクタを使用すると、すべてのインスタンスがプロトタイプメソッドを参照します。つまり、コンストラクタの方がメモリパフォーマンスが優れています。
フェデリコ

メモリが問題ではない場合、オブジェクトリテラルのプロパティアクセスは大幅に
Daniel Sokolowski

回答:


131

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

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

KISSの原則を適用します。単純なデータのコンテナー以外に何も必要ない場合は、単純なリテラルを使用します。

オブジェクトに動作を追加する場合は、コンストラクターを使用して、構築中にオブジェクトにメソッドを追加するか、クラスにプロトタイプを与えることができます。

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

ただし、これはカプセル化に関しては好ましくありません。理想的には、エンティティに関連付けられたすべてのデータ+動作が共存する必要があります。


12
すばらしい説明ですが、関数をオブジェクトリテラルに配置することについてはどうでしょうか。私はこれが以前に行われたのを見ました。実際、以下の投稿にはこの例があります。
チョボ

23
関数定義をオブジェクトリテラルの一部として含めるかthis.fn = function ...、コンストラクターでこのアプローチを使用する場合、オブジェクトインスタンスのそれぞれに独自の関数のコピーがあります。プロトタイプアプローチを使用して、各関数を1回だけアタッチします。これらの関数は、プロトタイプの継承を通じてインスタンスによって継承されます。
Ates Goral 2011

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

ゲームエンジンに移行するためのより良い方法は何でしょうか?コンストラクターメソッドを使用しましたが、プロトタイプからコンストラクターデータにアクセスできません。
zachdyer 2015年

90

基本的には、オブジェクトの複数のインスタンスが必要かどうかということになります。コンストラクタで定義されたオブジェクトを使用すると、そのオブジェクトの複数のインスタンスを作成できます。オブジェクトリテラルは、基本的にすべてパブリックな変数/メソッドを持つシングルトンです。

// 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 2014年

私の経験では、これがまさに違いを生むものです。素晴らしい明確な例。
エア・

9

均一な方法でオブジェクトを作成するもう1つの方法は、オブジェクトを返す関数を使用することです。

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!

JavaScriptの関数はクロージャなので、プライベート変数とメソッドを使用して回避できnewます。

JavaScriptのプライベート変数に関するhttp://javascript.crockford.com/private.htmlから。


7

以下のコードは、オブジェクトを作成する3つの方法、オブジェクトリテラル構文、関数コンストラクター、およびを示していObject.create()ます。オブジェクトリテラル構文__prototype__は、その場でオブジェクトを作成するだけなので、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);

1
関数をオブジェクトリテラル内で宣言したからです。つまりObject.create、リテラル内の関数を使用してオブジェクトを作成すると、インスタンスごとに一意になりますか?
JohnnyQ 2016年

6

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

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

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

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


関数とメソッドの違いは何ですか?私はc#のバックグラウンドから来ているので、私にとって関数はスタンドアロンであり、メソッドは単なるクラスの一部である関数です。
チョボ

1
それほど大きな違いはありません。たとえばweb-source.net/javascript_tutorial/…を参照してください。実際には、DOMscripting(ブラウザでクライアントサイドのJS)に、すべての機能がウィンドウ・オブジェクト(グローバル名前空間)の方法になる私はあなたがウィンドウとしてすべての「スタンドアロン」の機能に対応することができます(と言うでしょう[somefunction]。。
KooiInc

5

ここに画像の説明を入力してください

ページのオブジェクトの単一インスタンスが必要ですか-リテラル。

DTOオブジェクトのような単純なデータを転送するだけですか?GET SET:-Literal

メソッドの動作、複数のインスタンスを持つ実際のオブジェクトを作成しますか-コンストラクター関数、OOP原則に従う、継承:-コンストラクター関数。

以下は、リテラルとは何か、コンストラクタ関数とは何か、それらがどのように異なるのかを詳しく説明しているyoutubeビデオです。

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


1

オブジェクトリテラルを使用すると、初期値が導入されるため、より簡潔で拡張性が高くなります。


オブジェクトリテラルにプライベート変数をどのように作成しますか?
EhevuTov 2013

実際にはできません。元の質問には関係ないので、リンクを提供します。javascript.crockford.com
Tom

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

私は正直に言って、私の質問の最初の読みは、choboがパラメーターリストと単一オブジェクトリテラルパラメーターのように、コンストラクターに変数を渡す方法について尋ねていたということでした。
トム

1

https://www.w3schools.com/js/js_object_definition.aspで述べたように

オブジェクトリテラルを使用すると、 1 つの ステートメントで1 つのオブジェクトを定義および作成できます

また

オブジェクトリテラルは、単一のオブジェクトのみを作成します。1つのタイプの多くのオブジェクトを作成するために使用できるオブジェクトタイプが必要な場合があります



0

実際には、オブジェクトリテラルにプライベートメソッドを含めることができます。以下のコードを検討してください:

var myObject = {

   publicMethod: function () {
      privateMethod1();
      privateMethod2(); 
      function privateMethod1(){
          console.log('i am privateMethod1');
      } 
      function privateMethod2(){
          console.log('i am privateMethod2');
      } 
   }

}

好みの問題ですが、可能な場合はオブジェクトリテラルを使用することを好みます。


-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
あなたの例のどこでオブジェクトリテラルが宣言されていますか?
JohnnyQ 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.