Qual è la differenza tra `new Object ()` e notazione letterale dell’object?

Qual è la differenza tra questa syntax basata sul costruttore per la creazione di un object:

person = new Object() 

… e questa syntax letterale:

 person = { property1 : "Hello" }; 

Sembra che entrambi facciano la stessa cosa, anche se JSLint preferisce usare la notazione letterale dell’object.

Quale è meglio e perchè?

Entrambi fanno la stessa cosa (a meno che qualcuno non abbia fatto qualcosa di insolito), a parte il fatto che il tuo secondo crea un object e aggiunge una proprietà ad esso. Ma la notazione letterale richiede meno spazio nel codice sorgente. È chiaramente riconoscibile per ciò che sta accadendo, quindi usando il new Object() , stai solo digitando di più e (in teoria, se non ottimizzato dal motore JavaScript) facendo una chiamata di funzione non necessaria.

Queste

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

tecnicamente non fare la stessa cosa Il primo crea solo un object. Il secondo ne crea uno e assegna una proprietà. Perché il primo sia lo stesso, è necessario un secondo passaggio per creare e assegnare la proprietà.

Il “qualcosa di insolito” che qualcuno potrebbe fare sarebbe quello di ombreggiare o assegnare Object globale globale:

 // Don't do this Object = 23; 

In questo caso altamente insolito , il new Object fallirà ma {} funzionerà.

In pratica, non c’è mai un motivo per usare un new Object piuttosto che {} (a meno che tu non abbia fatto una cosa molto insolita).

Non c’è differenza per un object semplice senza metodi come nel tuo esempio. Tuttavia, c’è una grande differenza quando si inizia ad aggiungere metodi al proprio object.

Modo letterale:

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

Modo prototipo:

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

Entrambi i modi consentono la creazione di istanze di Obj questo modo:

 var foo = new Obj( "hello" ); 

Tuttavia, con il modo letterale, porti una copia del metodo sayHello all’interno di ciascuna istanza dei tuoi oggetti. Mentre, con la modalità prototipo, il metodo viene definito nel prototipo dell’object e condiviso tra tutte le istanze dell’object. Se hai molti oggetti o molti metodi, il modo letterale può portare a un grande spreco di memoria.

In JavaScript, possiamo dichiarare un nuovo object vuoto in due modi:

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

Non ho trovato nulla che suggerisca che ci siano differenze significative tra questi due riguardo al modo in cui operano dietro le quinte (correggimi se ho torto – mi piacerebbe saperlo). Tuttavia, il secondo metodo (utilizzando la notazione letterale dell’object) offre alcuni vantaggi.

  1. È più corto (10 caratteri per essere precisi)
  2. È più semplice e più strutturato per creare oggetti al volo
  3. Non importa se qualche buffone ha inavvertitamente sovrascritto l’object

Considera un nuovo object che contiene i membri Nome e TelNo. Usando la nuova convenzione Object (), possiamo crearla in questo modo:

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

La funzione Expando Properties di JavaScript ci consente di creare nuovi membri in questo modo al volo e otteniamo ciò che intendevamo. Tuttavia, in questo modo non è molto strutturato o incapsulato. E se volessimo specificare i membri al momento della creazione, senza dover fare affidamento sulle proprietà expando e sull’assegnazione post-creazione?

Qui è dove la notazione letterale dell’object può aiutare:

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

Qui abbiamo raggiunto lo stesso effetto in una riga di codice e significativamente meno caratteri.

Un’ulteriore discussione sui metodi di costruzione degli oggetti sopra può essere trovata su: JavaScript e Object Oriented Programming (OOP).

E infine, che dire dell’idiota che ha scavalcato Object? Pensavi che non fosse ansible? Bene, questo JSFiddle dimostra il contrario. L’uso della notazione letterale dell’object ci impedisce di cadere in fallo di questo buffone.

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

Sulla mia macchina che utilizza Node.js, ho eseguito quanto segue:

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

Nota, questa è un'estensione di ciò che si trova qui: Perché arr = [] più veloce di arr = new Array?

la mia uscita era la seguente:

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

così chiaramente {} e [] sono più veloci che usare nuovi per creare oggetti / array vuoti.

Tutti qui parlano delle somiglianze dei due. Farò notare le differenze.

  1. Usando il new Object() consente di passare un altro object. L’ovvio risultato è che l’object appena creato sarà impostato sullo stesso riferimento. Ecco un codice di esempio:

     var obj1 = new Object(); obj1.a = 1; var obj2 = new Object(obj1); obj2.a // 1 
  2. L’utilizzo non è limitato agli oggetti come negli oggetti OOP. Altri tipi potrebbero essere passati anche a questo. La funzione imposterà il tipo di conseguenza. Ad esempio se passiamo il numero intero 1 ad esso, verrà creato un object di tipo numero per noi.

     var obj = new Object(1); typeof obj // "number" 
  3. L’object creato utilizzando il metodo precedente ( new Object(1) ) verrà convertito in tipo di object se viene aggiunta una proprietà.

     var obj = new Object(1); typeof obj // "number" obj.a = 2; typeof obj // "object" 
  4. Se l’object è una copia di una class figlio di object, potremmo aggiungere la proprietà senza la conversione del 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 

In realtà, ci sono diversi modi per creare oggetti in JavaScript. Quando si desidera creare un object, non vi è alcun vantaggio nel creare oggetti basati sul costruttore usando l’operatore ” nuovo “. È come creare un object usando la syntax ” object literal “. Ma gli oggetti basati sul costruttore creati con l’operatore ” nuovo ” diventano incredibili quando si pensa a ” eredità prototipale “. Non è ansible mantenere la catena di ereditarietà con oggetti creati con la syntax letterale. Ma puoi creare una funzione di costruzione , colbind proprietà e metodi al suo prototipo. Quindi, se si assegna questa funzione di costruzione a qualsiasi variabile utilizzando l’operatore ” nuovo “, verrà restituito un object che avrà accesso a tutti i metodi e le proprietà associate al prototipo di tale funzione di costruzione.

Ecco un esempio di creazione di un object usando la funzione di costruzione (vedi la spiegazione del codice in fondo):

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

Ora puoi creare tutti gli oggetti che vuoi istanziando la funzione di costruzione di Person e tutti erediteranno fullname () da esso.

Nota: la parola chiave ” this ” farà riferimento a un object vuoto all’interno di una funzione di costruzione e ogni volta che crei un nuovo object da Persona utilizzando l’operatore ” nuovo ” restituirà automaticamente un object contenente tutte le proprietà e i metodi associati alla parola chiave ” this ” . E questi oggetti erediteranno sicuramente i metodi e le proprietà associati al prototipo della funzione di costruzione di Person (che è il vantaggio principale di questo approccio).

A proposito, se volessi ottenere la stessa funzionalità con la syntax ” object literal “, dovresti creare fullname () su tutti gli oggetti come di seguito:

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

Infine, se ora chiedi perché dovrei usare l’approccio della funzione di costruzione invece dell’approccio letterale dell’object :

*** L’ereditarietà prototipale consente una semplice catena di ereditarietà che può essere immensamente utile e potente.

*** Salva la memoria ereditando i metodi e le proprietà comuni definiti nel prototipo delle funzioni di costruzione. Altrimenti, dovresti copiarli più e più volte in tutti gli oggetti.

Spero che abbia senso.

Inoltre, secondo alcuni dei libri di javascript di O’Really …. (citato)

Un altro motivo per utilizzare i letterali rispetto al costruttore Object è che non esiste una risoluzione dell’ambito. Poiché è ansible che tu abbia creato un costruttore locale con lo stesso nome, l’interprete deve cercare la catena dell’ambito dal punto in cui stai chiamando Object () fino a quando non trova il costruttore Object globale.

Ho trovato una differenza, per ES6 / ES2015. Non è ansible restituire un object usando la syntax della funzione freccia stenografica, a meno che non si circonda l’object con 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 } ] 

Questo perché il compilatore è confuso dalle parentesi {} e pensa n: i è un’etichetta: costrutto statement ; il punto e virgola è facoltativo, quindi non si lamenta.

Se si aggiunge un’altra proprietà all’object, verrà generato un errore.

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

L’utilizzo della memoria è diverso se si creano 10 mila istanze. new Object() conserverà solo una copia mentre {} manterrà 10 mila copie.