2015-06-12 17 views
41

Quindi, sto osservando le specifiche ES5 alla definizione di cosa new Object e Object do. Con mia grande sorpresa:`new Object` vs` Object` nella specifica ECMAScript

  • new Object descrive un intero algoritmo di come funziona il costruttore dell'oggetto - il trattamento di ciò che accade con diversi tipi di valori. Fondamentalmente chiama ToObject su non oggetti: identità su oggetti e build su null e non definiti.
  • Object ha un primo passaggio speciale per null e undefined dove crea un oggetto e quindi chiama ToObject su primitive e identità sugli oggetti.

Dopo aver letto la descrizione alcune volte, il numero sembra identico allo. Tuttavia, chiaramente dalle specifiche fanno qualcosa di diverso. Per esempio in Array - chiamando new Array è specificato come the function call Array(…) is equivalent to the object creation expression new Array(…) with the same arguments.`

Quindi - qual è la differenza tra il new Object e Object? Perché erano specificati in modo diverso?

Per semplicità: ecco uno link to the spec.

+0

JS room people (ovvero Jan Drovak) ha pensato che abbia a che fare con gli oggetti host ma non riuscivo a capirne uno che facesse realmente la differenza. –

+0

'new Object' è definito dall'implementazione sugli oggetti host. Mi piacerebbe ancora vedere un esempio di quando non è un'identità. –

+14

Questa sarà una di quelle famose domande? –

risposta

16

Object(window) non clonerà mai window ma new Object(window) potrebbe. Tutte le implementazioni correnti, potenzialmente tutte note, restituiscono lo stesso riferimento, sebbene le specifiche consentano un comportamento definito dall'implementazione.

I passaggi per 15.2.1.1 dire:

  1. Se il valore è nullo, non definito o non fornito, creare e restituire un nuovo oggetto oggetto esattamente come se lo standard incorporato costruzione Object era stato chiamato con gli stessi argomenti
  2. Return ToObject (valore).

La definizione di ToObject (9.9) elenca alcuni tipi che verranno catturati da passaggio 1 (nella tavola 14), ma per Object ha una definizione molto semplice:

Il risultato è l'argomento di input (nessuna conversione).

In modo esplicito afferma che l'argomento di input verrà restituito così com'è, quindi dovrebbero essere riferimenti uguali (===).

La definizione di new Object (15.2.2.1) presenta una simile catena di tipo controlli nella fase 1, ma la fase di oggetti (1.a) è:

i. Se il valore è un oggetto nativo ECMAScript, non creare un nuovo oggetto ma semplicemente restituire un valore.

ii. Se il valore è un oggetto host, vengono eseguite le azioni e viene restituito un risultato in un modo dipendente dall'implementazione che può dipendere dall'oggetto host.

Cioè, per qualsiasi oggetto host foo, la chiamata Object(foo) mosto === foo ma new Object(foo) possono === foo.

oggetti host sono definiti in 4.3.8 essere

dell'oggetto fornito dall'ambiente host per completare l'ambiente di esecuzione di ECMAScript.

This answer liste alcuni oggetti host per includere window, history, ecc Esecuzione di quelli attraverso new Object(foo)dovrebbe (ma non deve) restituire un oggetto diverso.

In ogni caso ma passando un oggetto host, new Object(foo) sembra essere una catena più complicato che differisce a ToObject meno allo stesso modo come Object(foo).

Sfortunatamente, 15.2.2.1.1.a.ii afferma che "il risultato viene restituito in modo dipendente dall'implementazione" e non ha specifiche relative alle "azioni [che sono state prese" e sembra che Chrome restituire lo stesso oggetto (riferimenti uguali) per tutti gli "oggetti host" elencati.

Usando questo script per controllare:

var objects = [ 
 
    /* Native objects */ 
 
    'Object', 'Date', 'Math', 'parseInt', 'eval', 
 
    /* Host objects */ 
 
    'window', 'document', 'location', 'history', 'XMLHttpRequest', 'setTimeout' 
 
]; 
 

 
function getDefinedReference(name) { 
 
    if (eval('typeof ' + name) !== 'undefined') { 
 
    return eval(name); 
 
    } else { 
 
    throw new Error('' + name + ' is not defined.'); 
 
    } 
 
} 
 

 
function checkIdentity(name) { 
 
    try { 
 
    var ref = getDefinedReference(name); 
 
    var no = new Object(ref); 
 
    var o = Object(ref); 
 

 
    console.log(name, ref === no, ref === o, no === o); 
 

 
    if (ref === o && no !== o) { 
 
     // Make sure ref === Object(ref) but not new Object(ref) 
 
     console.log(name, 'returns different references.'); 
 
    } 
 
    } catch (e) { 
 
    console.warn(e); 
 
    } 
 
} 
 

 
objects.forEach(checkIdentity); 
 

 
if (typeof window !== 'undefined') { 
 
    for (var f in window) { 
 
    checkIdentity(f); 
 
    } 
 
}

non si trova alcun oggetto in cui Object e new Object si comportano in modo diverso. @ Xotic750 sembra avere ragione che può essere dipendente dall'implementazione, ma nessuno lo sta usando.

+1

Riesci a trovare un'implementazione e un oggetto host che differisce tra 'Object' e' new Object'? –

+0

@BenjaminGruenbaum ancora alla ricerca. Sospetto fortemente che questo sia qualcosa che la specifica consente, ma nessuno sta usando, ma una suite di test non può ferire. – ssube

+0

@AwalGarg che due oggetti appena creati non sono uguali ai riferimenti - come '{} === {}' –

Problemi correlati