`new Object ()`와 객체 리터럴 표기법의 차이점은 무엇입니까?


199

객체 생성을위한이 생성자 기반 구문의 차이점은 무엇입니까?

person = new Object()

... 그리고이 리터럴 구문 :

person = {
    property1 : "Hello"
};

JSLint는 객체 리터럴 표기법을 선호하지만 둘 다 동일한 작업을 수행하는 것으로 보입니다.

어느 것이 더 좋고 왜?


7
모두 같은 : a = new Object, a = new Object(), a = {}, 문자는 훨씬 간단하고 전에 더 빨리, 더 새로운 컴파일러 내 문을 허위로 원인이 될 수라고하면서 몇 가지 검사가 나는 달렸다. 리터럴 배열에도 동일하게 적용
Juan Mendes

8
var글로벌 네임 스페이스를 오염시키지 않고 변수의 스택에서 현재 레코드를 넘어야 할 필요성을 피하기 위해 응용 프로그램 코드에서 키워드로 변수를 선언하기 를 바랍니다.
Samo

1
기본적으로 프로그램 실행 중 어느 시점에서든 레코드 또는 블록 스택이 있습니다. 각 레코드에는 해당 범위에서 작성된 변수 목록이 있습니다. JavaScript에서 표현식에 변수가 포함되어 있고 인터프리터가 해당 범위의 스택 레코드에서 변수를 찾을 수없는 경우 변수를 찾을 때까지 다음 레코드로 계속 올라갑니다. 자세한 정보 davidshariff.com/blog/…
Samo

2
JSLint를 피하는 것은 좋은 개발자가되기위한 첫 단계입니다. 사용 new은 평범한 언어의 무의미한 nitpicking을 초월하는 규칙입니다. new그 의미가 분명하기 때문에 사용하십시오 . 이 경우 99.9 %에서 성능 향상과 관련이 없습니다.
Hal50000

1
누구에 따라 @ Hal50000 평범한 언어?
Xam

답변:


124

그들은 모두 같은 일을 할 것 이외의 (이상한 사람의 완료 뭔가하지 않는 한), 두 번째 하나는 객체를 생성 하고 여기에 속성을 추가합니다. 그러나 리터럴 표기법은 소스 코드에서 공간을 덜 차지합니다. 무슨 일이 일어나고 있는지 분명히 알 수 있으므로new Object() 하면 실제로 더 많은 것을 입력하고 (이론적으로 JavaScript 엔진에 의해 최적화되지 않은 경우) 불필요한 함수 호출을 수행합니다.

이들

person = new Object() /*You should put a semicolon here too.  
It's not required, but it is good practice.*/ 
-or-

person = {
    property1 : "Hello"
};

기술적으로 같은 일을하지 마십시오. 첫 번째는 객체를 만듭니다. 두 번째는 하나를 만들고 속성을 할당합니다. 첫 번째 것이 동일하려면 속성을 만들고 할당하는 두 번째 단계가 필요합니다.

누군가가 할 수있는 "비정상적인 것"은 기본 Object전역 을 가리거나 할당하는 것입니다 .

// Don't do this
Object = 23;

점에서 높은 특이한 경우, new Object실패하지만,{} 작동합니다.

실제로 new Object{}(이 매우 특이한 일을하지 않은 경우) 보다 사용할 이유가 없습니다 .


11
저자는이 답변을 정답으로 선택했지만 불완전합니다. 메모리 할당에 들어가면 두 구문 사이에 차이점이 있습니다.
newshorts

2
차이점은 없습니다. 아래 답변 중 하나를 언급하는 경우 프로토 타입 기반 객체 모델 및 상속 (일반 객체에서 상속되는 Obj 클래스를 설정하는 코드)에 대해 이야기 할 때 주제가 맞지 않습니다. 이 질문은 사용자 정의 클래스의 인스턴스를 만드는 것이 아닙니다. Object의 인스턴스를 만드는 것입니다.이 질문에 대한 정답은 "차이가 없습니다"입니다.
dos

참고로 () new Object()필요하지 않습니다. (필요하지 않은 것에 대해 이야기)
Royi Namir

현재 사양대로 new 를 사용할 필요는 없다고 생각 합니다. 의견을 보내주세요 @kevin
Vamsi Pavan Mahesh

1
상속 체인에서 상속되지 않는 객체를 원할 경우 Object create를 사용하고 null을 전달할 수도 있습니다. 그것들은 동등하지 않으며 각각 유용한 목적을 가지고 있습니다.
Aaron

234

예제와 같이 메소드가없는 간단한 객체에는 차이가 없습니다. 그러나 객체에 메소드를 추가하기 시작하면 큰 차이가 있습니다.

리터럴 방식 :

function Obj( prop ) { 
    return { 
        p : prop, 
        sayHello : function(){ alert(this.p); }, 
    }; 
} 

프로토 타입 방식 :

function Obj( prop ) { 
    this.p = prop; 
} 
Obj.prototype.sayHello = function(){alert(this.p);}; 

두 가지 방법으로 다음 Obj과 같은 인스턴스를 만들 수 있습니다 .

var foo = new Obj( "hello" ); 

그러나 문자 그대로의 방법으로 sayHello객체의 각 인스턴스 내에 메소드 의 사본을 가지고 있습니다. 반면 프로토 타입 방식에서는 메소드가 오브젝트 프로토 타입에 정의되어 모든 오브젝트 인스턴스간에 공유됩니다. 많은 객체 또는 많은 메소드가있는 경우 문자 그대로의 방법으로 인해 상당한 메모리 낭비가 발생할 수 있습니다.


39
나에게 질문은 빈 객체를 만드는 데 new Object()vs {}를 사용하는 것의 차이점에 관한 것 입니다.
Peter

11
@Lobabob 첫 번째 문장 외에도이 답변은 실제로 OP의 질문에 대한 정보를 제공하지 않습니다. 심지어 'new Object ()'도 포함하지 않습니다. 솔직히 데이비드 씨가 그 질문을 오해 한 것 같습니다.
JLRishe

17
내가 이것을 게시했을 때 수락 된 답변이 이미 있었고 수락했습니다. 그리고 그것은 OP 질문에 완벽하게 대답하므로 동일한 것을 반복하지 않을 것입니다. 나는 빈 / 간단한 물체를 넘어서 주제를 넓히기 위해 주로 답을 올렸다. 어떤 경우에는 언급 할 가치 있는 중요한 차이점이 있습니다.
Rémy DAVID

3
이 답변은 주제에 맞지 않습니다. 코드에서 Obj는 Object에서 상속되는 별도의 클래스입니다. 객체 리터럴 표기법을 사용할 때는 Obj가 아닌 Object 클래스를 사용합니다. 물론 프로토 타입에 메소드를 사용하여 클래스를 설정하면 많은 일반 오브젝트를 작성하고 특성으로 메소드를 추가하는 것보다 메모리 풋 프린트를 작게 만들지 만 여기에서 묻는 질문과는 전혀 관련이 없습니다. 이 질문에 대한 정답은 "아니요, 전혀 차이가 없습니다 (가독성을 제외하고)"입니다.
dos

3
나는 내 것과 비슷한 질문을 바탕 으로이 대답을 얻었지만 정확히 알아야 할 것을 배우게되었습니다. 감사합니다.
Pat Migliaccio

55

JavaScript에서 우리는 두 가지 방법으로 새로운 빈 객체를 선언 할 수 있습니다 :

var obj1 = new Object();  
var obj2 = {};  

나는 그들이이 무대 뒤에서 어떻게 작동하는지에 관해이 두 가지 큰 차이점이 있음을 시사하는 것을 찾지 못했다 (내가 틀렸다면 나를 교정해라 – 알고 싶다). 그러나 두 번째 방법 (객체 리터럴 표기법 사용)은 몇 가지 장점을 제공합니다.

  1. 짧습니다 (정확한 10 자)
  2. 객체를보다 쉽고 빠르게 생성 할 수있는 구조화
  3. 일부 버푼이 실수로 객체를 재정의했는지 여부는 중요하지 않습니다.

Name 및 TelNo 멤버를 포함하는 새 오브젝트를 고려하십시오. 새로운 Object () 규칙을 사용하여 다음과 같이 만들 수 있습니다.

var obj1 = new Object();  
obj1.Name = "A Person";  
obj1.TelNo = "12345"; 

는 Expando 속성JavaScript 기능을 사용하면 이런 방식으로 새 멤버를 즉시 만들 수 있으며 의도했던 것을 달성 할 수 있습니다. 그러나이 방법은 구조화되거나 캡슐화되지 않습니다. expando 속성 및 할당 후 생성에 의존하지 않고 생성시 멤버를 지정하려면 어떻게해야합니까?

여기에 객체 리터럴 표기법이 도움이 될 수 있습니다.

var obj1 = {Name:"A Person",TelNo="12345"};  

여기서 우리는 한 줄의 코드에서 동일한 효과를 달성했으며 문자 수가 훨씬 적었습니다.

위의 객체 구성 방법에 대한 자세한 내용은 JavaScript 및 객체 지향 프로그래밍 (OOP) 에서 확인할 수 있습니다 .

마지막으로 Object를 대체 한 바보는 무엇입니까? 불가능하다고 생각 했습니까? 글쎄, 이 JSFiddle 달리 증명한다. 객체 리터럴 표기법을 사용하면 우리가이 버릇을 파울 수 없습니다.

( http://www.jameswiseman.com/blog/2011/01/19/jslint-messages-use-the-object-literal-notation/에서 )


1
Object.Create는 어떻습니까? 참조 : developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Phil

new Object()무언가 객체 기능을 덮어 쓸 가능성 때문에 객체 리터럴을 선호한다면 , Object.keys정의되지 않은 것을 확인하기 위해 도우미를 사용할 때 도처에 경비원 을 작성해야합니다. 나는 항상 사람들이 문자 표기법을 사용하도록 권장하지만, 당신이 그런 식으로 생각한 결과를 생각할 때이 특별한 주장이 분리된다고 생각합니다.
philraj

41

Node.js를 사용하는 컴퓨터에서 다음을 실행했습니다.

console.log('Testing Array:');
console.time('using[]');
for(var i=0; i<200000000; i++){var arr = []};
console.timeEnd('using[]');

console.time('using new');
for(var i=0; i<200000000; i++){var arr = new Array};
console.timeEnd('using new');

console.log('Testing Object:');

console.time('using{}');
for(var i=0; i<200000000; i++){var obj = {}};
console.timeEnd('using{}');

console.time('using new');
for(var i=0; i<200000000; i++){var obj = new Object};
console.timeEnd('using new');

이것은 다음에서 발견되는 것의 확장입니다. arr = []가 arr = new Array보다 빠른 이유는 무엇입니까?

내 결과는 다음과 같습니다.

Testing Array:
using[]: 1091ms
using new: 2286ms
Testing Object:
using{}: 870ms
using new: 5637ms

따라서 빈 객체 / 배열을 만드는 데 new를 사용하는 것보다 {} 및 []가 더 빠릅니다.


3
나는 이것이 실제로 질문에 대한 답이라고 생각하지만, 몇 가지 속성을 가진 객체에서 이것을 추가로 테스트하고 싶었습니다.
체이스 샌드 만

2
재미있는 숫자. 이것을 알아야 할 사람들이 있지만, 약 200,000 개의 객체조차 할당하는 데 5.6ms의 비용이 들기 때문에 걱정하지 않아도됩니다.

노드 10.13.0에서 테스트 배열 변경 : using [] : 117.178ms new를 사용하여 : 116.947ms Testing Object : using {} : new를 사용하여 116.252ms : 115.910ms
PirateApp

31

여기의 모든 사람들은이 둘의 유사점에 대해 이야기하고 있습니다. 차이점을 지적하겠습니다.

  1. 를 사용 new Object()하면 다른 객체를 전달할 수 있습니다. 명백한 결과는 새로 작성된 오브젝트가 동일한 참조로 설정된다는 것입니다. 다음은 샘플 코드입니다.

    var obj1 = new Object();
    obj1.a = 1;
    var obj2 = new Object(obj1);
    obj2.a // 1
  2. 사용법은 OOP 객체에서와 같이 객체로 제한되지 않습니다. 다른 유형도 전달 될 수 있습니다. 이 기능은 그에 따라 유형을 설정합니다. 예를 들어 정수 1을 전달하면 숫자 유형의 객체가 생성됩니다.

    var obj = new Object(1);
    typeof obj // "number"
  3. 위의 방법 ( new Object(1))을 사용하여 생성 된 객체 는 속성이 추가되면 객체 유형으로 변환됩니다.

    var obj = new Object(1);
    typeof obj // "number"
    obj.a = 2;
    typeof obj // "object"
  4. 객체가 객체의 하위 클래스의 복사 본인 경우 유형 변환없이 속성을 추가 할 수 있습니다.

    var obj = new Object("foo");
    typeof obj // "object"
    obj === "foo" // true
    obj.a = 1;
    obj === "foo" // true
    obj.a // 1
    var str = "foo";
    str.a = 1;
    str.a // undefined

3
나는 마지막 두 줄에 대해 매우 혼란스러워합니다. 왜 str.a에 값 1을 할당하면 str.a가 정의되지 않습니까? .. @Jermin Bazazin
Andrea Scarafoni

3
@AndreaScarafoni str는 유형 string이므로 속성을 할당 할 수 없습니다. jsfiddle.net/grq6hdx7/1
Chris Bier

1
4에 대한 답변이 변경 되었습니까? 나는 최근에 크롬 53, 참, 거짓되지 얻을 var obj = new Object("foo"); typeof obj; obj === "foo" // true
윌리엄 힐튼

21

실제로 JavaScript로 객체를 생성하는 방법에는 여러 가지가 있습니다. 객체를 만들고 싶을 때는 " new "연산자를 사용하여 " 생성자 기반 "객체를 만들면 아무런 이점이 없습니다 . " 객체 리터럴 "구문을 사용하여 객체를 만드는 것과 같습니다 . 그러나 " new "연산자로 생성 된 " 생성자 기반 "개체 는 " 프로토 타입 상속 "에 대해 생각할 때 매우 유용합니다 . 리터럴 구문으로 작성된 오브젝트로 상속 체인을 유지할 수 없습니다. 그러나 생성자 함수를 만들고 속성과 메서드를 프로토 타입에 연결할 수 있습니다 ."연산자를 사용하면 해당 생성자 함수의 프로토 타입에 연결된 모든 메서드 및 속성에 액세스 할 수있는 개체가 반환됩니다.

다음은 생성자 함수를 사용하여 객체를 생성하는 예입니다 (하단의 코드 설명 참조).

function Person(firstname, lastname) {
    this.firstname = firstname;
    this.lastname = lastname;
}

Person.prototype.fullname = function() {
    console.log(this.firstname + ' ' + this.lastname);
}

var zubaer = new Person('Zubaer', 'Ahammed');
var john = new Person('John', 'Doe');

zubaer.fullname();
john.fullname();

이제 Person 생성 함수를 인스턴스화하여 원하는 수의 객체를 만들 수 있으며 모든 객체는 fullname ()을 상속합니다.

참고 : " this "키워드는 생성자 함수 내에서 빈 객체를 참조하며 " new "연산자를 사용하여 Person에서 새 객체를 만들 때마다 " this "키워드로 연결된 모든 속성과 메서드가 포함 된 객체를 자동으로 반환 합니다. . 그리고이 객체는 Person 생성자 함수 의 프로토 타입 에 첨부 된 메소드와 속성을 확실히 상속합니다 (이 접근 방식의 주요 이점).

그런데 " 객체 리터럴 "구문 과 동일한 기능을 얻으려면 다음과 같이 모든 객체에 대해 fullname ()을 만들어야합니다.

var zubaer = {
    firstname: 'Zubaer',
    lastname: 'Ahammed',
    fullname: function() {
        console.log(this.firstname + ' ' + this.lastname);
    }
};

var john= {
    firstname: 'John',
    lastname: 'Doe',
    fullname: function() {
        console.log(this.firstname + ' ' + this.lastname);
    }
};

zubaer.fullname();
john.fullname();

마지막으로, 왜 객체 리터럴 접근법 대신 생성자 함수 접근법을 사용해야하는지 묻는다면 :

*** 프로토 타입 상속은 매우 유용하고 강력 할 수있는 간단한 상속 체인을 허용합니다.

*** 생성자 함수 프로토 타입에 정의 된 공통 메소드 및 특성을 상속하여 메모리를 절약합니다. 그렇지 않으면 모든 객체에서 반복해서 복사해야합니다.

이것이 의미가 있기를 바랍니다.


감사! 객체 리터럴에 누락 된 "this"를 추가 한 Karl 끔찍한 실수 였어요. 이런 종류의 실수를해서는 안됩니다.
Md. Zubaer Ahammed

"리터럴 구문으로 생성 된 객체에서 상속 할 수 없습니다." -사실이 아닙니다 (믿습니다). 필요에 따라 상속 체인을 사용 Object.create(<object defined using literal notation>)하거나 new Object(<object defined using literal notation>)생성 할 수 있습니다 .
balajeerc

@balajeerc 의견을 보내 주셔서 감사합니다. 실제로는 "리터럴 구문으로 작성된 객체로 상속 체인을 유지할 수 없습니다"여야합니다. 대답은 여러 단계로 이루어집니다. 1. Object.create () : 예, 객체 리터럴을 전달할 수 있으며 프로토 타입이 객체 리터럴을 전달한 새 객체를 반환합니다. 그러나 생성자 함수가 무엇인지 모르거나 생성 된 객체 리터럴을 기억하지 못합니다. 따라서 testobj1.constructor는 빈 함수를 반환하며 부모 / 조상으로서 해당 객체 리터럴에 속성 / 메소드를 추가 할 수있는 방법이 없습니다.
Md. Zubaer Ahammed

@balajeerc 2. new Object () :이 경우에도 거의 같은 일이 발생합니다. 또한 메모리에 대해 생각하면 나빠집니다. 속성과 메서드를 프로토 타입에 넣는 대신 전달 된 개체 리터럴의 모든 내용을 복사하여 반환 된 개체에 넣습니다. 메모리에 좋지 않습니다. 반면에, 나는 즉시 메소드와 속성을 편집 할 수있는 생성자 함수를 사용하여 진정한 상속 체인에 중점을 두었습니다. 생성자 메소드를 사용하여 생성 된 다른 객체도 복사하는 대신 생성자 함수를 가리키는 경우에만 영향을받습니다 .
Md. Zubaer Ahammed

@balajeerc 예 :function Person(firstname, lastname) { this.firstname = firstname; this.lastname = lastname; } Person.prototype.fullname = function() { console.log(this.firstname + ' ' + this.lastname); } var zubaer = new Person('Zubaer', 'Ahammed'); var john = new Person('John', 'Doe'); zubaer.fullname(); // Zubaer Ahammed john.fullname(); // John Doe zubaer.constructor.prototype.fullname = function() { console.log( 'Hello ' + this.firstname); } zubaer.fullname(); // Hello Zubaer john.fullname(); // Hoello John
Zubaer Ahammed Md.

9

또한, O'Really 자바 스크립트 책 중 일부에 따르면 ... (인용)

Object 생성자와 달리 리터럴을 사용하는 또 다른 이유는 범위 확인이 없기 때문입니다. 동일한 이름으로 로컬 생성자를 만들었을 수 있으므로 인터프리터는 전역 Object 생성자를 찾을 때까지 Object ()를 호출하는 위치에서 스코프 체인을 찾아야합니다.


24
O'Really가 오타이거나 고의적 인 말장난 이었습니까? 그들은 그것을 도서 마케팅에 사용해야합니다!
Tim Ogilvy

3

ES6 / ES2015의 한 가지 차이점을 발견했습니다. 으로 객체를 둘러싸 지 않으면 단축 화살표 함수 구문을 사용하여 객체를 반환 할 수 없습니다 new Object().

> [1, 2, 3].map(v => {n: v});
[ undefined, undefined, undefined ]
> [1, 2, 3].map(v => new Object({n: v}));
[ { n: 1 }, { n: 2 }, { n: 3 } ]

컴파일러가 {}대괄호 로 혼란스럽고 레이블 이라고 생각 n: i하기 때문 입니다. statement construct; 세미콜론은 선택 사항이므로 불평하지 않습니다.

객체에 다른 속성을 추가하면 결국 오류가 발생합니다.

$ node -e "[1, 2, 3].map(v => {n: v, m: v+1});"
[1, 2, 3].map(v => {n: v, m: v+1});
                           ^

SyntaxError: Unexpected token :

4
당신은 여전히 ​​화살표 기능을 사용할 수 있습니다, 당신은 더 많은 중괄호와 반환이 필요합니다 : [1, 2, 3].map(v => { return {n: v}; });당신에게 같은 것을 그물 것입니다 ...
Heretic Monkey

물론 일반 화살표 기능을 사용할 수 있습니다, 나는 약 말하고 있었는지 약식 버전, 즉이었다 param => return_value, 그리고 사용의 차이 {}new Object()이 경우는.
Andrei Simionescu

11
축약 형 버전과 일반 화살표 기능을 계속 사용할 수 있습니다. {n : v}를 한 쌍의 괄호로 감싸면됩니다.[1, 2, 3].map(v => ({n: v}));
Stephen C

1

2019 년 업데이트

OSX High Sierra 10.13.6 노드 버전 10.13.0에서 @rjloura와 동일한 코드를 실행했으며 결과는 다음과 같습니다.

console.log('Testing Array:');
console.time('using[]');
for(var i=0; i<200000000; i++){var arr = []};
console.timeEnd('using[]');

console.time('using new');
for(var i=0; i<200000000; i++){var arr = new Array};
console.timeEnd('using new');

console.log('Testing Object:');

console.time('using{}');
for(var i=0; i<200000000; i++){var obj = {}};
console.timeEnd('using{}');

console.time('using new');
for(var i=0; i<200000000; i++){var obj = new Object};
console.timeEnd('using new');


Testing Array:
using[]: 117.613ms
using new: 117.168ms
Testing Object:
using{}: 117.205ms
using new: 118.644ms

-2

10,000 개의 인스턴스를 생성하면 메모리 사용량이 다릅니다. new Object()사본은 한 장만 보관하고 {}10,000 장은 보관합니다.


7
new새 객체를 만듭니다. 둘 다 같은 양의 메모리를 사용합니다.
Artyer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.