Qual é a diferença entre `new Object ()` e notação literal de object?

Qual é a diferença entre esta syntax baseada em construtor para criar um object:

person = new Object() 

… e esta syntax literal:

 person = { property1 : "Hello" }; 

Parece que ambos fazem a mesma coisa, embora o JSLint prefira usar a notação literal do object.

Qual deles é melhor e por quê?

Ambos fazem a mesma coisa (a menos que alguém tenha feito algo incomum), além de que o segundo cria um object e adiciona uma propriedade a ele. Mas a notação literal ocupa menos espaço no código-fonte. É claramente reconhecível quanto ao que está acontecendo, portanto, usando o new Object() , você está realmente digitando mais e (em teoria, se não otimizado pelo mecanismo JavaScript) fazendo uma chamada de function desnecessária.

Estes

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

tecnicamente não fazem a mesma coisa. O primeiro apenas cria um object. O segundo cria um e atribui uma propriedade. Para o primeiro ser o mesmo, você precisa de um segundo passo para criar e atribuir a propriedade.

O “algo incomum” que alguém poderia fazer seria sombrear ou atribuir ao Object global padrão:

 // Don't do this Object = 23; 

Nesse caso altamente incomum , o new Object falhará, mas {} funcionará.

Na prática, nunca há um motivo para usar o new Object vez de {} (a menos que você tenha feito algo muito incomum).

Não há diferença para um object simples sem methods como no seu exemplo. No entanto, há uma grande diferença quando você começa a adicionar methods ao seu object.

Forma literal:

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

Forma de protótipo:

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

Ambas as formas permitem a criação de instâncias de Obj assim:

 var foo = new Obj( "hello" ); 

No entanto, com a maneira literal, você carrega uma cópia do método sayHello dentro de cada instância de seus objects. Considerando que, com o caminho do protótipo, o método é definido no protótipo do object e compartilhado entre todas as instâncias do object. Se você tiver muitos objects ou muitos methods, a maneira literal pode levar a um grande desperdício de memory.

Em JavaScript, podemos declarar um novo object vazio de duas maneiras:

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

Não encontrei nada que sugira que haja alguma diferença significativa em relação a como eles operam nos bastidores (por favor corrija-me se estiver errado – eu adoraria saber). No entanto, o segundo método (usando a notação literal do object) oferece algumas vantagens.

  1. É mais curto (10 caracteres para ser preciso)
  2. É mais fácil e mais estruturado criar objects em tempo real
  3. Não importa se algum buffoon inadvertidamente substituiu Object

Considere um novo object que contenha os membros Name e TelNo. Usando a nova convenção Object (), podemos criá-lo assim:

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

O recurso Propriedades de Expando do JavaScript nos permite criar novos membros dessa maneira e atingimos o que pretendíamos. No entanto, desta forma não é muito estruturado ou encapsulado. E se quiséssemos especificar os membros após a criação, sem precisar depender da propriedade expando e da pós-criação da atribuição?

É aqui que a notação literal do object pode ajudar:

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

Aqui conseguimos o mesmo efeito em uma linha de código e significativamente menos caracteres.

Uma discussão adicional sobre os methods de construção de objects acima pode ser encontrada em: JavaScript e Object Oriented Programming (OOP).

E finalmente, e o idiota que cancelou o Object? Você achou que não era possível? Bem, este JSFiddle prova o contrário. Usando a notação literal do object nos impede de cair em falta desta bufonaria.

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

Na minha máquina usando o Node.js, eu corri o seguinte:

 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'); 

Note que esta é uma extensão do que é encontrado aqui: Por que arr = [] é mais rápido que arr = new Array?

minha saída foi a seguinte:

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

tão claramente {} e [] são mais rápidos do que usar o novo para criar objects / matrizes vazios.

Todos aqui estão falando sobre as semelhanças dos dois. Eu vou apontar as diferenças.

  1. Usando o new Object() permite que você passe outro object. O resultado óbvio é que o object recém-criado será definido para a mesma referência. Aqui está um código de exemplo:

     var obj1 = new Object(); obj1.a = 1; var obj2 = new Object(obj1); obj2.a // 1 
  2. O uso não está limitado a objects como em objects OOP. Outros tipos podem ser passados ​​para ele também. A function irá definir o tipo de acordo. Por exemplo, se passarmos o inteiro 1 para ele, um object do tipo number será criado para nós.

     var obj = new Object(1); typeof obj // "number" 
  3. O object criado usando o método acima ( new Object(1) ) seria convertido para o tipo de object se uma propriedade for adicionada a ele.

     var obj = new Object(1); typeof obj // "number" obj.a = 2; typeof obj // "object" 
  4. Se o object for uma cópia de uma class de object filho, poderíamos adicionar a propriedade sem a conversão de tipo.

     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 

Na verdade, existem várias maneiras de criar objects no JavaScript. Quando você quer apenas criar um object, não há benefício em criar objects ” baseados em construtor ” usando o operador ” novo “. É o mesmo que criar um object usando a syntax ” object literal “. Mas os objects ” baseados em construtor ” criados com o operador ” novo ” são de uso incrível quando se pensa em ” inheritance prototípica “. Você não pode manter a cadeia de inheritance com objects criados com a syntax literal. Mas você pode criar uma function de construtor , append propriedades e methods ao seu protótipo. Então, se você atribuir essa function construtora a qualquer variável usando o operador ” new “, ela retornará um object que terá access a todos os methods e propriedades anexados ao protótipo dessa function construtora.

Aqui está um exemplo de criação de um object usando a function construtora (veja explicação do código na parte inferior):

 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(); 

Agora, você pode criar quantos objects desejar, instanciando a function de construção Person e todos eles herdarão fullname () dela.

Nota: ” this ” palavra-chave se referirá a um object vazio dentro de uma function construtora e sempre que você criar um novo object de Person usando o operador ” new ” ele retornará automaticamente um object contendo todas as propriedades e methods anexados com a palavra-chave ” this ” . E esses objects com certeza herdarão os methods e propriedades anexados ao protótipo da function construtora Person (que é a principal vantagem dessa abordagem).

By the way, se você quisesse obter a mesma funcionalidade com a syntax ” object literal “, você teria que criar fullname () em todos os objects como abaixo:

 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(); 

Por fim, se você agora perguntar por que devo usar a abordagem de function de construtor em vez da abordagem literal de object :

*** Prototypal inheritance permite uma cadeia simples de inheritance que pode ser imensamente útil e poderosa.

*** Ele economiza memory ao herdar methods e propriedades comuns definidos no protótipo de funções do construtor. Caso contrário, você teria que copiá-los repetidamente em todos os objects.

Espero que isto faça sentido.

Além disso, de acordo com alguns dos livros de javascript O’Really …. (citado)

Outro motivo para usar literais ao contrário do construtor Object é que não há resolução de escopo. Como é possível que você tenha criado um construtor local com o mesmo nome, o intérprete precisa procurar a cadeia de escopo desde o local em que você está chamando Object () até encontrar o construtor global Object.

Eu encontrei uma diferença, para ES6 / ES2015. Você não pode retornar um object usando a syntax da function de seta abreviada, a menos que você envolva o object com o 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 } ] 

Isso ocorre porque o compilador é confundido pelos {} colchetes e acha que n: i é uma construção label: statement ; o ponto e vírgula é opcional, por isso não se queixa.

Se você adicionar outra propriedade ao object, ele finalmente lançará um erro.

 $ 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 : 

O uso de memory é diferente se você criar 10 mil instâncias. new Object() só manterá uma cópia enquanto {} manterá 10 mil cópias.