Quello che sta accadendo nella tecnica la creazione di oggetti di Crockford?
-
03-10-2019 - |
Domanda
Ci sono solo 3 linee di codice, ma sto avendo problemi completamente afferrare questo:
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
newObject = Object.create(oldObject);
-
Object.create()
inizia con la creazione di una funzione vuoto chiamatoF
. Sto pensando che una funzione è un tipo di oggetto. Dove si trova questo oggettoF
essere conservato? Globalmente immagino. -
Avanti nostro
oldObject
, passato comeo
, diventa il prototipo della funzioneF
. Funzione (vale a dire, oggetto)F
ora "eredita" dalla nostraoldObject
, nel senso che la risoluzione dei nomi percorso volontà attraverso di essa. Buono, ma sono curioso di ciò che il prototipo di default è per un oggetto, oggetto? Che è vero anche per una funzione-oggetto? -
Infine,
F
viene creata un'istanza e restituito, diventando il nostronewObject
. È l'operazionenew
strettamente necessario qui? NonF
già a disposizione quello che ci serve, o c'è una differenza fondamentale tra oggetti-funzione e non-oggetti-funzione? Chiaramente non sarà possibile avere una funzione di costruzione utilizzando questa tecnica.
Che cosa succede la prossima volta Object.create()
si chiama? È la funzione F
globale sovrascritto? Sicuramente non viene riutilizzato, perché ciò alterare oggetti precedentemente configurati. E cosa succede se più thread chiamano Object.create()
, non v'è alcun tipo di sincronizzazione per evitare condizioni di gara su F
?
Soluzione
1) Object.create () inizia da creando una funzione vuoto chiamato F. Sto pensando che una funzione è un genere dell'oggetto. Dov'è questo oggetto F essere memorizzati? Globalmente immagino.
No, è memorizzato sulla portata locale della funzione Object.create
, ogni volta che si richiama Object.create
questa funzione F
verrà ricreato.
Si potrebbe anche creare una memoria-efficiente implementazione di più, memorizzando F
su una chiusura, e riutilizzarlo:
if (typeof Object.create !== "function") {
Object.create = (function () {
function F() {} // created only once
return function (o) {
F.prototype = o; // reused on each invocation
return new F();
};
})();
}
2) Avanti nostro oldObject, passato come o, diventa il prototipo della funzione F. Funzione (cioè, oggetto) F ora "eredita" dalla nostra oldObject, nel percepire che instraderà la risoluzione dei nomi attraverso esso. Buono, ma sono curioso di ciò che il prototipo di default è per un oggetto Oggetto? Che è vero anche per la un oggetto-funzione?
Tutti gli oggetti hanno una proprietà interna che costruisce la catena di prototipi, questa struttura è conosciuta come [[Prototype]]
, è una proprietà interna, anche se alcune implementazioni consentono di accedere ad esso, come Mozilla, con la proprietà obj.__proto__
.
Il [[Prototype]]
di default quando si crea un nuovo oggetto, vale a dire var obj = {};
è Object.prototype
.
Tutte le funzioni hanno una proprietà prototype
, questa proprietà viene utilizzata quando una funzione viene usato come un Constructor , invocato con l'operatore new
.
Una nuova istanza dell'oggetto è creato dietro le quinte, e questo oggetto [[Prototype]]
è impostato per la sua proprietà prototype
Costruttori.
3) Infine, F e viene creata un'istanza tornato, diventando il nostro newObject. È l'operazione "nuova" strettamente necessario Qui? Non F già fornire ciò abbiamo bisogno, o c'è una critica differenza tra oggetti-funzione e non-oggetti-funzione? chiaramente non sarà possibile avere un funzione di costruzione che utilizza questo tecnica.
Sì, l'operatore new
è essenziale in questo metodo.
L'operatore new
è il modo unico standard per impostare la proprietà interna [[Prototype]]
di un oggetto, se siete curiosi di sapere come funziona, si può dare uno sguardo al [[Construct]]
funzionamento interno.
Che cosa succede la prossima volta Object.create () si chiama? è globale funzione F sovrascritto? Sicuramente è non riutilizzato, perché ciò alterare precedentemente configurato oggetti. E cosa accade se più thread chiamano Object.create (), c'è qualche sorta di la sincronizzazione per evitare gara condizioni F?
La prossima volta Object.create
viene richiamato, una nuova funzione F
locale viene creata un'istanza solo nell'ambito della chiamata al metodo, non si deve preoccupare di condizioni di gara .
Si noti che questa implementazione è conforme a malapena il Object.create
descritto nella ECMAScript 5th Edition specifiche , a quel metodo, si potrebbe passare un descrittore di proprietà per inizializzare l'oggetto.
Tutti i produttori di browser stanno attuando esso (già disponibile su Firefox 3.7 Alpha, ultima Wekit nightly build e Chrome 5 beta), quindi vi consiglio di almeno per verificare se esistono un'implementazione nativa prima di override di esso.
Altri suggerimenti
1) Una funzione è infatti un tipo di oggetto. Un oggetto funzione con identificativo F
viene creata ogni volta Object.create
viene chiamato, ed è accessibile solo mediante tale identificatore all'interno di tale esecuzione Object.create
. Pertanto, ogni volta che viene chiamato Object.create
, si ottiene un diverso F
funzione di oggetto. Questa funzione di oggetto vite sulla come proprietà constructor
dell'oggetto restituito da Object.create
.
2)
F ora "eredita" dalla nostra oldObject, nel senso che la risoluzione dei nomi volontà percorso attraverso di essa
Questo non è propriamente corretto. Assegnazione di un someObject
oggetto alla proprietà prototype
di una funzione significa solo che il prototipo di un oggetto futuro creato da chiamare questa funzione come un costruttore sarà someObject
.
3) La new
è assolutamente vitale per questa tecnica. Solo chiamando una funzione come un costruttore fa produrre un nuovo oggetto, e il prototipo di quell'oggetto (che non è generalmente accessibile) è impostato alla proprietà prototype
della funzione di costruzione. Non c'è altra (standardizzato) modo per impostare il prototipo di un oggetto.
Infine, JavaScript nei browser è single threaded, quindi condizioni di gara, come si descrive non sono possibili.
Il grande equivoco è che F ha portata globale. Si dichiara nel corpo di Object.create e conseguentemente è solo in ambito entro quel blocco metodo.
> Chiaramente non sarà possibile avere una funzione di costruzione utilizzando questa tecnica.
La tecnica è già un costruttore di oggetto in quanto restituisce nuova F (), ma non i valori delle proprietà può essere impostata come per dire uomo nuovo ( 'John', 'Smith'). Tuttavia, se il codice Object.create viene modificato, è possibile esemplificazione. Ad esempio l'oggetto sarah seguito possono essere costruite e un'istanza utilizzando Object.creator, e erediterà il metodo getName.
var girl = {
name: '',
traits: {},
getName: function(){return this.name}
}
var sarah = Object.creator(girl, 'Sarah', {age:29,weight:90})
L'oggetto sarah sarà quindi composto da proprie caratteristiche {nome: 'Sarah', tratti: {Età: 9, peso: 49}}, e il prototipo ereditato sarah.getName () produrrà 'Sarah'
Il seguente metodo si basa sulle proprietà propri enumerazione con 'per (prop in o)' in ordine di creazione. Anche se non garantita da specifiche ECMA, questo esempio (e qualche più complesso) ha lavorato per tutti i principali browser (4) testato, providied hasOwnProperty () è stato utilizzato, altrimenti no.
Object.creator = function(o) {
var makeArgs = arguments
function F() {
var prop, i=1, arg, val
for(prop in o) {
if(!o.hasOwnProperty(prop)) continue
val = o[prop]
arg = makeArgs[i++]
if(typeof arg === 'undefined') break
this[prop] = arg
}
}
F.prototype = o
return new F()
}
L'ECMA Object.create ufficiale ha un secondo parametro opzionale, propertiesObject, che può istanziare i valori delle proprietà, ma è un oggetto piuttosto che il solito elenco, e sembra scomodo da utilizzare. Per esempio. Credo che: -
o2 = Object.create({}, { p: { value: 42, writable: true, enumerable: true, configurable: true } });
è equivalente alla vecchia maniera molto più semplice: -
o2 = new function(p) { this.p=p }(42)
e
o2 = Object.creator({p:''}, 42)