В чем разница между новой версией Object() и объектной литературой?

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

person = new Object()

... и этот литеральный синтаксис:

person = {
    property1 : "Hello"
};

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

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

Ответ 1

Они оба делают то же самое (если кто-то не делает что-то необычное), кроме того, что ваш второй создает объект и добавляет к нему свойство. Но буквальное обозначение занимает меньше места в исходном коде. Он четко распознает, что происходит, поэтому, используя new Object(), вы действительно просто печатаете больше и (теоретически, если не оптимизированы движком JavaScript), выполняете ненужный вызов функции.

Эти

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

person = {
    property1 : "Hello"
};

технически не делают то же самое. Первый просто создает объект. Вторая создает одно и присваивает свойство. Для того, чтобы первый был таким же, вам понадобится второй шаг для создания и назначения свойства.

"Что-то необычное", которое мог сделать кто-то, было бы теневым или назначить по умолчанию Object global:

// Don't do this
Object = 23;

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

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

Ответ 2

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

Литературный путь:

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

Ответ 3

В JavaScript мы можем объявить новый пустой объект двумя способами:

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

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

  • Короче (точнее, 10 символов)
  • Это проще и более структурировано для создания объектов на лету
  • Не имеет значения, если какой-нибудь шутер случайно переопределил Object

Рассмотрим новый объект, содержащий элементы Name и TelNo. Используя новое соглашение Object(), мы можем создать его следующим образом:

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

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

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

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

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

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

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

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

Ответ 4

На моей машине с помощью 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 = новый массив?

Мой результат был следующим:

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

так ясно {} и [] быстрее, чем использовать new для создания пустых объектов/массивов.

Ответ 5

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

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

    var obj1 = new Object();
    obj1.a = 1;
    var obj2 = new Object(obj1);
    obj2.a // 1
    
  • Использование не ограничено объектами, как в объектах ООП. Другие типы также могут быть переданы ему. Функция будет соответствующим образом устанавливать тип. Например, если мы передадим ему целое число 1, для нас будет создан объект типа номера.

    var obj = new Object(1);
    typeof obj // "number"
    
  • Объект, созданный с использованием вышеуказанного метода (new Object(1)), будет преобразован в тип объекта, если к нему добавлено свойство.

    var obj = new Object(1);
    typeof obj // "number"
    obj.a = 2;
    typeof obj // "object"
    
  • Если объект является копией дочернего класса объекта, мы можем добавить свойство без преобразования типа.

    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
    

Ответ 6

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

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

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

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

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

Ответ 7

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

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

Ответ 8

Я нашел одно отличие для 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 является label: 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 :

Ответ 9

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

Ответ 10

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