In breve:
new something2() instanceof something2 === false
relazione a ciò, se si estende il vostro esempio di utilizzare la proprietà prototipo
Something.prototype.method = function() { };
something2.prototype.method = function() { };
troverete che il prototipo non è ereditato in quest'ultimo caso:
typeof (new Something()).method === "function"
type (new something2()).method === "undefined"
Il rea La risposta è che stai attingendo a meccanismi di fondo completamente diversi.La chiamata con new
richiama il meccanismo [[Construct]], che implica l'impostazione della proprietà [[Prototipo]] in base alla proprietà .prototype
del costruttore.
Ma una cosa divertente accade nei passaggi 8--10 dell'algoritmo [[Costruisci]]: dopo aver impostato un nuovo oggetto vuoto e quindi collegato il suo [[Prototipo]], fa un [[Call] ] al costruttore effettivo, utilizzando questo nuovo oggetto empty-plus-prototype come this
. E poi, al punto 9, se si scopre che quel costruttore ha restituito qualcosa --- getta via quell'oggetto prototipally, passato-come- this
che ha trascorso tutto quel tempo a settare!
Nota: è possibile accedere di un oggetto [[Prototype]] (che è diversa da quella di un costruttore .prototype
) con Object.getPrototypeOf
:
Object.getPrototypeOf(new Something()) === Something.prototype // steps 5 & 6
Object.getPrototypeOf(new something2()) === Object.prototype // default
di rispondere ad alcune meta-domande:
- No, non utilizzare maiuscole
something2
, poiché è una funzione di fabbrica e non un costruttore. Se qualcosa è in maiuscolo, ci si aspetta che abbia la semantica del costruttore, ad es. new A() instanceof A
.
- Se si è preoccupati del pericolo di oscuramento dello spazio dei nomi globale, è necessario iniziare a utilizzare strict mode, inserendo
"use strict";
nella parte superiore dei file. Una delle tante piacevoli operazioni di pulizia della modalità rigorosa è che il valore predefinito di this
è undefined
, non l'oggetto globale, quindi ad es. chiamare un costruttore senza new
causerà errori nel momento in cui il costruttore tenta di collegare le proprietà a undefined
.
- Le funzioni di fabbrica (dette anche "schema di chiusura") sono in generale un ragionevole sostituto per costruttori e classi, purché non si usi (a) l'ereditarietà; (b) non costruire troppe istanze di quell'oggetto. Quest'ultimo è perché, nel modello di chiusura, si allega una nuova istanza di ogni metodo per ogni oggetto appena creato, il che non è ottimale per l'utilizzo della memoria. Il payoff più grande, IMO, del pattern di chiusura è la possibilità di utilizzare "private" variables (che sono uno good thing e non consentire a nessuno di dirti diversamente: P).
Essere un po 'diffidenti di Mr Crockford. Sebbene abbia molte cose buone da dire, ha delle opinioni che non sono d'accordo. – staticsan