В чем разница между `new Object ()` и литеральной нотацией объекта? - PullRequest
187 голосов
/ 04 января 2011

В чем разница между этим синтаксисом на основе конструктора для создания объекта:

person = new Object()

... и этим буквальным синтаксисом:

person = {
    property1 : "Hello"
};

Кажется, что оба делаютТо же самое, хотя JSLint предпочитает использовать буквенное обозначение объекта.

Какой из них лучше и почему?

Ответы [ 10 ]

221 голосов
/ 29 августа 2012

Нет разницы для простого объекта без методов, как в вашем примере. Однако есть большая разница, когда вы начинаете добавлять методы к вашему объекту.

Буквальный путь:

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 в каждом экземпляре ваших объектов. Принимая во внимание, что при использовании способа прототипа метод определяется в прототипе объекта и используется всеми экземплярами объекта. Если у вас много объектов или методов, буквальный путь может привести к довольно большой трате памяти.

116 голосов
/ 04 января 2011

Они оба делают одно и то же (если кто-то не сделал что-то необычное), кроме того, что ваш второй создает объект , а добавляет ему свойство.Но буквенная запись занимает меньше места в исходном коде.Понятно, что происходит, поэтому, используя 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 global:

// Don't do this
Object = 23;

В этом крайне необычном случае new Object не удастся, но {} сработает.

На практике нет причин использовать new Object, а не {} (если вы не сделали эту очень необычную вещь).

53 голосов
/ 01 апреля 2011

В 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"; 

Функция JavaScript 101 * Expando Properties позволяет нам создавать новых участников таким образом на лету, и мы достигаем того, что намеревались. Однако этот способ не очень структурирован или не заключен в капсулу. Что если мы захотим указать членов при создании, не полагаясь на свойства expando и назначение после создания?

Здесь могут помочь буквенные обозначения объекта:

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

Здесь мы добились того же эффекта в одной строке кода и значительно меньше символов.

Дальнейшее обсуждение вышеуказанных методов конструирования объектов можно найти по адресу: JavaScript и объектно-ориентированное программирование (ООП).

И, наконец, что за идиот, который отверг Объект? Вы думали, что это было невозможно? Ну, этот JSFiddle доказывает обратное. Использование буквенной нотации объекта предотвращает нас от этой грязи.

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

40 голосов
/ 29 января 2014

На моей машине с помощью 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 для создания пустых объектов / массивов.

30 голосов
/ 14 декабря 2012

Все здесь говорят о сходстве двух.Я собираюсь указать на различия.

  1. Использование new Object() позволяет передавать другой объект.Очевидным результатом является то, что вновь созданный объект будет установлен на ту же ссылку.Вот пример кода:

    var obj1 = new Object();
    obj1.a = 1;
    var obj2 = new Object(obj1);
    obj2.a // 1
    
  2. Использование не ограничено объектами, как в объектах ООП.Другие типы могут быть переданы ему тоже.Функция установит тип соответственно.Например, если мы передадим ему целое число 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
    
17 голосов
/ 02 августа 2016

На самом деле, есть несколько способов создания объектов в JavaScript.Когда вы просто хотите создать объект, нет смысла создавать объекты " на основе конструктора ", используя оператор " new ".Это то же самое, что создание объекта с использованием синтаксиса " object literal ".Но объекты на основе конструктора , созданные с помощью оператора " 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 " будет ссылаться на пустой объект внутри функции конструктора, и всякий раз, когда вы создаете новый объект из Person с помощью оператора " new ", оно будетавтоматически возвращать объект, содержащий все свойства и методы, связанные с ключевым словом " this ".И этот объект наверняка унаследует методы и свойства, связанные с прототипом функции конструктора Person (что является основным преимуществом этого подхода).

Кстати, если вы хотеличтобы получить ту же функциональность с синтаксисом " object literal ", вам необходимо создать 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();

Наконец, если вы сейчас спроситепочему я должен использовать функцию конструктора подход вместо объектный литерал подход:

*** Прототипное наследование позволяет простую цепочку наследования, которая может быть чрезвычайно полезной и мощной.

*** Экономит память, наследуя общие методы и свойства, определенные в прототипе функций конструктора.В противном случае вам придется копировать их снова и снова во всех объектах.

Надеюсь, это имеет смысл.

8 голосов
/ 22 февраля 2013

Кроме того, согласно некоторым книгам о O'Really Javascript .... (цитируется)

Еще одна причина использования литералов в отличие от конструктора объекта - отсутствие разрешения области видимости. Поскольку возможно, что вы создали локальный конструктор с тем же именем, интерпретатору необходимо искать цепочку областей действия от места, где вы вызываете Object (), до тех пор, пока он не найдет глобальный конструктор Object.

3 голосов
/ 14 апреля 2016

Я нашел одно отличие для 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 метка: оператор конструкция;точка с запятой необязательна, поэтому не жалуется на это.

Если вы добавите другое свойство к объекту, оно, наконец, выдаст ошибку.

$ 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 :
0 голосов
/ 13 апреля 2019

2019 Обновление

Я выполнил тот же код, что и @rjloura, на моем узле OSX High Sierra 10.13.6 версии 10.13.0, и вот результаты

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
0 голосов
/ 13 июня 2016

Использование памяти отличается, если вы создаете 10 тысяч экземпляров. new Object() сохранит только одну копию, а {} сохранит 10 тысяч копий.

...