2012-03-16 13 views
5

ES5 ha aggiunto uno number di methods a Object, che sembrano rompere la coerenza semantica di JavaScript.Perché i metodi oggetto ES5 non sono stati aggiunti a Object.prototype?

Ad esempio, prima di questa estensione, l'API JavaScript girava sempre attorno all'operando su l'oggetto stesso;

var arrayLength = [].length; 
var firstPosInString = "foo".indexOf("o"); 

... dove sono come i nuovi metodi Oggetto;

var obj = { }; 
Object.defineProperty(obj, { 
    value: 'a', 
    writable: false 
}); 

... quando il seguente sarebbe stato molto più conformativa:

var obj = { }; 
obj.defineProperty({ 
    value: 'a', 
    writable: false 
}); 

Qualcuno può raffreddare la mia curiosità sul motivo per cui questo è? C'è qualche frammento di codice che potrebbe rompersi? Ci sono discussioni pubbliche fatte dal comitato di normazione sul motivo per cui hanno scelto questo approccio?

risposta

5

Questo è tutto spiegato molto bene in "Proposed ECMAScript 3.1 Static Object Functions: Use Cases and Rationale" document (pdf) da Allen Wirfs-Brock stesso (editor di ES5 spec, e un membro di TC39).

Vorrei suggerire di leggere tutto. È piuttosto breve, facilmente digeribile e offre una panoramica dei processi mentali alla base di queste aggiunte ES5.

Ma per dirla con relativa sezione (sottolineatura mia):

Un certo numero di alternative disegni API sono stati considerati prima della proposto API è stato scelto. Nel corso del considerare le alternative, abbiamo sviluppato un insieme di linee guida informali che abbiamo applicato quando considerando le alternative. Queste linee guida sono:

  • Cleanly separare i metadati e di applicazione strati.
  • Provare a ridurre al minimo l'area di superficie dell'API (ovvero il numero di metodi e la complessità dei relativi argomenti).
  • Concentrarsi sull'usabilità nella denominazione e nella progettazione dei parametri.
  • Prova ad applicare ripetutamente elementi di base di un disegno.
  • Se possibile, abilitare i programmatori o le implementazioni per ottimizzare staticamente gli usi dell'API.

[...]

Ecco alcune delle alternative che sono stati considerati che portano alla il disegno selezionato.

L'idea iniziale ovvio, seguendo l'esempio del metodo standard già esistente Object.prototype.propertyIsEnumerable, sia aggiungere “piano terreno ...” ulteriori metodi di query su Object.prototype per gli altri attributi e un parallelo insieme di metodi di modifica degli attributi.

[...]

Come abbiamo considerato questo approccio ci sono stati una serie di cose su di esso che non ci piace e che sembrava in contrasto con il design API sopra linee guida:

  • È che unisce anziché separare i livelli meta e applicazione. Come metodi su Object.prototype, i metodi farebbero parte dell'interfaccia pubblico di ogni oggetto applicazione in un programma. Come tale, hanno bisogno di per essere compreso da tutti gli sviluppatori, non solo dai progettisti di librerie.

[...]

+0

Interessante ... sai come è stato allineato con' Object.create'? Crockford lo propose come "Object.create" dopo che erano state prese queste decisioni, o prima? –

+0

Buona domanda. Non ne ho idea :) Penso che Crockford abbia ribattezzato il suo 'Object.beget' in' Object.create' all'incirca nello stesso momento in cui sono state discusse queste API. FWIW, il documento dice: _ 'Nota che Object.create senza il suo secondo argomento opzionale è essenzialmente la stessa operazione della funzione di beget che è stata ampiamente promossa. Noi (forse non sorprendentemente) siamo d'accordo con l'utilità di questa funzione ma sentiamo che la parola "generare" è probabilmente confusa con molti non di madrelingua inglese. " – kangax

+3

Crockford fu direttamente coinvolto nel progetto ES5 e originariamente propose di" generare ". "creare" è emerso come il nome preferito durante le successive discussioni sul design. Ha ribattezzato "beget" nel suo libro per riflettere la decisione di progettazione ES. –

1

l'API JavaScript girava sempre attorno all'operando sull'oggetto stesso;

Questo non è corretto. Per esempio. JSON e Math hanno sempre avuto i propri metodi. Nessuno fa queste cose:

var x = 0; 
x.cos(); // 1.0 
({"a":[0,1],"p":{"x":3,"y":4}}).toJSON(); 

Ci sono numerosi articoli sul web circa il motivo per cui si estende Object.prototype è una brutta cosa. Sì, si tratta del codice del client, ma forse questo non è valido per i metodi di build-in anche per alcuni punti.

+1

prendo il tuo punto circa 'Math' ... ma le differenze tra l'estensione' Object.prototype' come client * * e come il linguaggio stesso sono completamente diverse ; le estensioni per * lingua * non compaiono in 'for (in)', dove come * estensioni * client *: http://jsfiddle.net/mDfCe/1/ – Isaac

+0

Ah, sì. Mi sbaglio. – kirilloid

+0

... che è dovuto al fatto che tali proprietà ('.constructor',' .hasOwnProperty' ecc.) Sono definite nativamente con l'attributo "enumerable" impostato su false. A partire da ES5 possiamo anche creare le nostre proprietà che non appaiono nei cicli "for in" (con "Object.defineProperty" e il secondo argomento di Object.create') – Krinkle

Problemi correlati