객체 리터럴이나 생성자 함수를 사용해야합니까?


94

나는 자바 스크립트에서 객체를 생성 해야하는 방법에 대해 혼란스러워합니다. 적어도 두 가지 방법이있는 것 같습니다. 하나는 객체 리터럴 표기법을 사용하는 것이고 다른 하나는 구성 함수를 사용하는 것입니다. 하나의 장점이 다른 것보다 있습니까?


1
가장 좋은 대답 : stackoverflow.com/questions/4597926/…- 요약하면, 리터럴 표기법으로 인스턴스를 생성하는 함수를 설정할 수도 있습니다. 이렇게하면 각 인스턴스가 모든 메서드를 전달하는 반면 생성자를 사용하면 모든 인스턴스가 프로토 타입 메서드를 참조합니다. 즉 생성자는 더 나은 메모리 성능을 가지고 있습니다.
Federico

메모리가 문제가 객체 리터럴 속성에 액세스 할 경우 더 빨리 많은 크기는 - jsperf.com/module-pattern-vs-object-literal-vs-prototype/4
다니엘 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
훌륭한 설명이지만 객체 리터럴에 함수를 넣는 것은 어떻습니까? 나는 이것을 전에 본 적이 있습니다. 실제로 아래 게시물에는 이에 대한 예가 있습니다.
chobo

23
함수 정의를 객체 리터럴의 일부로 포함하거나 this.fn = function ...생성자 에서 접근 방식을 사용하는 경우 각 객체 인스턴스에는 자체 함수 복사본이 있습니다. 프로토 타입 접근 방식을 사용하면 각 함수를 한 번만 연결합니다. 프로토 타입 상속을 통해 인스턴스에 상속됩니다.
Ates Goral

14
중요한 것을 놓친 것 같습니다. 생성자 함수 만이 개인 멤버와 공용 멤버를 제공 할 수 있습니다 (캡슐화). 객체 리터럴에서-모두 공개됩니다.
Royi Namir

게임 엔진으로가는 더 좋은 방법은 무엇입니까? 생성자 메서드를 사용했지만 프로토 타입이 생성자 데이터에 액세스 할 수 없습니다.
zachdyer

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

제 경험상 이것이 바로 차이를 만드는 것입니다. 아주 분명한 예입니다.
Air

9

균일 한 방식으로 객체를 생성하는 또 다른 방법은 객체를 반환하는 함수를 사용하는 것입니다.

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.

에서 http://javascript.crockford.com/private.html 자바 스크립트에서 private 변수에.


7

아래 코드는 객체를 생성하는 세 가지 방법 인 Object Literal 구문, 함수 생성자 및 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

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

이제 방법 multiply5에서 myObjSomeLiteral정확히 같은 일을. 유일한 차이점은 myObj가 전용 변수를 사용한다는 것입니다. 후자는 경우에 따라 유용 할 수 있습니다. 대부분의 경우 객체 리터럴은 충분하고 JS 객체를 생성하는 훌륭하고 깨끗한 방법입니다.


함수와 메서드의 차이점은 무엇입니까? 저는 ac # 배경에서 왔기 때문에 함수는 독립형이고 메서드는 클래스의 일부인 함수일뿐입니다.
chobo

1
그다지 차이가 ​​없습니다 . 예를 들어 web-source.net/javascript_tutorial/…을 참조하십시오 . 실제로 DOMscripting (브라우저의 클라이언트 측 js)에서 모든 함수는 window-object (글로벌 네임 스페이스)의 메서드가됩니다 (모든 '독립 실행 형'함수를 window. [somefunction]로 처리 할 수 ​​있습니다.)
KooiInc

5

여기에 이미지 설명 입력

페이지에 대한 개체의 단일 인스턴스를 원하십니까-Literal.

DTO 개체와 같은 데이터를 간단하게 전송하고 싶습니까? GET SET :-Literal

메서드 동작, 다중 인스턴스-생성자 함수, OOP 원칙 따르기, 상속 :-생성자 함수를 사용하여 실제 개체를 만들고 싶습니까?

아래는 리터럴이 무엇인지, 생성자 함수가 무엇이며 서로 어떻게 다른지 자세히 설명하는 YouTube 동영상입니다.

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


1

객체 리터럴로 이동하면 초기 값의 도입으로 더 간결하고 더 잘 확장됩니다.


객체 리터럴에서 개인 변수를 어떻게 생성합니까?
EhevuTov 2013 년

당신은 정말로 할 수 없습니다, 그것은 원래 질문과 관련이 없으므로 링크를 제공하겠습니다 : javascript.crockford.com/private.html
Tom

1
실제로 차이가있는 곳에는 특정 상황에 따라 둘 중 하나를 사용하는 이유가 있기 때문에 관련이 있습니다. 이 경우 개인 변수를 원하는지 여부입니다. 먼저 리터럴에서 클로저 함수를 생성하여 리터럴에서 개인 변수를 만들 수 있지만 제 생각에는 훨씬 추하고 읽기가 어렵습니다.
EhevuTov 2013 년

나는 정정 당했고, 질문에 대한 원래 읽은 것은 chobo가 매개 변수 목록과 단일 객체 리터럴 매개 변수에서와 같이 생성자에 변수를 전달하는 방법에 대해 묻는 것입니다.


0

Object () 생성자 함수는 조금 더 느리고 장황합니다. 따라서 JavaScript에서 새 개체를 만드는 데 권장되는 방법은 리터럴 표기법을 사용하는 것입니다.

Udacity 객체 지향 JavaScript


0

사실, methinks, 우리는 객체 리터럴에 private 메서드를 가질 수 있습니다. 아래 코드를 고려하십시오.

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
귀하의 예에서 Object 리터럴은 어디에 선언되어 있습니까?
JohnnyQ
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.