Il prototipo
la proprietà è un oggetto creato da JavaScript per ogni Funzione()
esempio. In particolare, collega le istanze dell'oggetto create con nuovo
parola chiave torna alla funzione di costruzione che li ha creati. Questo è fatto in modo che le istanze possano condividere, o ereditare, metodi e proprietà comuni. È importante sottolineare che la condivisione si verifica durante la ricerca della proprietà. Ricorda dal primo articolo che ogni volta che cerchi o accedi a una proprietà su un oggetto, la proprietà verrà ricercata sull'oggetto e sulla catena del prototipo.
Un oggetto prototipo viene creato per ogni funzione, indipendentemente dal fatto che si intenda utilizzare tale funzione come costruttore.
Nel codice seguente, costruisco un array dal Array ()
costruttore, e poi invoco il aderire()
metodo.
Esempio: sample118.html
Il aderire()
il metodo non è definito come una proprietà di myArray
istanza di oggetto, ma in qualche modo abbiamo accesso a aderire()
come se lo fosse. Questo metodo è definito da qualche parte, ma dove? Bene, è definito come una proprietà del Array ()
proprietà prototipo del costruttore. Da aderire()
non si trova all'interno dell'istanza dell'oggetto dell'array, JavaScript cerca la catena del prototipo per un metodo chiamato aderire()
.
Ok, allora perché le cose sono fatte in questo modo? In realtà, si tratta di efficienza e riutilizzo. Perché ogni istanza dell'array creata dalla funzione di costruzione dell'array deve essere definita in modo univoco aderire()
metodo quando aderire()
funziona sempre allo stesso modo? Ha più senso per tutti gli array sfruttare lo stesso aderire()
funzione senza dover creare una nuova istanza della funzione per ogni istanza di array.
Questa efficienza di cui parliamo è possibile a causa del prototipo
proprietà, il collegamento del prototipo e la catena di ricerca del prototipo. In questo articolo, suddividiamo questi attributi spesso confusi dell'ereditarietà prototipale. Ma a dire il vero, starai meglio memorizzando semplicemente i meccanismi di come funziona effettivamente la gerarchia delle catene. Fare riferimento al primo articolo se è necessario un aggiornamento su come vengono risolti i valori delle proprietà.
prototipo
Proprietà?Dovresti preoccuparti per il prototipo
proprietà per quattro motivi.
La prima ragione è che la proprietà prototype viene utilizzata dalle funzioni di costruzione native (Oggetto()
, Array ()
, Funzione()
, ecc.) per consentire alle istanze del costruttore di ereditare proprietà e metodi. È il meccanismo utilizzato da JavaScript stesso per consentire alle istanze dell'oggetto di ereditare proprietà e metodi dalle funzioni del costruttore prototipo
proprietà. Se vuoi capire meglio JavaScript, devi capire in che modo lo stesso JavaScript sfrutta il prototipo
oggetto.
Quando si creano funzioni di costruzione definite dall'utente, è possibile orchestrare l'ereditarietà allo stesso modo degli oggetti nativi JavaScript. Ma prima devi imparare come funziona.
Potresti non gradire l'ereditarietà del prototipo o preferire un altro modello per l'ereditarietà degli oggetti, ma in realtà un giorno potresti dover modificare o gestire il codice di qualcun altro che pensava che l'eredità prototipale fosse le ginocchia delle api. Quando ciò accade, devi essere a conoscenza di come funziona l'ereditarietà prototipale, nonché del modo in cui può essere replicata dagli sviluppatori che fanno uso di funzioni di costruzione personalizzate.
Utilizzando l'ereditarietà prototipale, è possibile creare istanze di oggetti efficienti che sfruttano tutti gli stessi metodi. Come già accennato, non tutti gli oggetti dell'array, che sono istanze del Array ()
costruttore, hanno bisogno di loro aderire()
metodi. Tutte le istanze possono sfruttare lo stesso aderire()
metodo perché il metodo è memorizzato nella catena del prototipo.
Funzione()
istanzeTutte le funzioni sono create da a Funzione()
costruttore, anche se non invochi direttamente il Funzione()
costruttore (var add = new Function ('x', 'y', 'return x + z');
) e utilizzare invece la notazione letterale (var add = function (x, y) return x + z;
).
Quando viene creata un'istanza di funzione, viene sempre data a prototipo
proprietà, che è un oggetto vuoto. Nel seguente esempio, definiamo una funzione chiamata myFunction e quindi accediamo a prototipo
proprietà che è semplicemente un oggetto vuoto.
Esempio: sample119.html
Assicurati di comprendere completamente che la proprietà del prototipo proviene dal Funzione()
costruttore. Solo una volta che intendiamo utilizzare la nostra funzione come funzione di costruzione definita dall'utente, la proprietà del prototipo viene sfruttata, ma ciò non cambia il fatto che Funzione()
costruttore fornisce ad ogni istanza una proprietà prototipo.
prototipo
La proprietà è un Oggetto()
OggettoTutto questo prototipo
parlare può diventare un po 'pesante. Veramente, prototipo
è solo una proprietà di oggetto vuota chiamata "prototipo" creata dietro le quinte da JavaScript e resa disponibile invocando il Funzione()
costruttore. Se dovessi farlo manualmente, sarebbe simile a questo:
Esempio: sample120.html
In effetti, questo codice di esempio funziona davvero bene, essenzialmente solo la duplicazione di ciò che JavaScript già fa.
Il valore di una proprietà prototype può essere impostato su uno qualsiasi dei valori complessi (oggetti) disponibili in JavaScript. JavaScript ignorerà qualsiasi proprietà prototipo impostata su un valore primitivo.
prototipo
ProprietàMentre è solo un oggetto, prototipo
è speciale perché la catena prototipo collega ogni istanza alla proprietà prototipo della sua funzione di costruzione. Ciò significa che ogni volta che un oggetto viene creato da una funzione di costruzione usando il nuovo
keyword (o quando viene creato un object wrapper per un valore primitivo), aggiunge un collegamento nascosto tra l'istanza dell'oggetto creata e la proprietà prototype della funzione di costruzione utilizzata per crearlo. Questo collegamento è noto all'interno dell'istanza come __proto__
(sebbene sia esposto / supportato tramite codice in Firefox 2+, Safari, Chrome e Android). JavaScript lo collega insieme in background quando viene invocata una funzione di costruzione e questo link che consente alla catena di prototipi di essere, beh, una catena. Nel seguente esempio, aggiungiamo una proprietà al nativo Array ()
costruttori prototipo
, che possiamo quindi accedere da un Array ()
istanza usando il __proto__
proprietà impostata su quell'istanza.
Esempio: sample121.html
Dall'accesso __proto__
non fa parte dello standard ufficiale ECMA, c'è un modo più universale per tracciare il collegamento da un oggetto all'oggetto prototipo che eredita, e cioè utilizzando il costruttore
proprietà. Questo è dimostrato nel seguente esempio.
Esempio: sample122.html
In questo esempio, il foo
la proprietà si trova all'interno dell'oggetto prototipo. È necessario rendersi conto che ciò è possibile solo a causa dell'associazione tra l'istanza di Array ()
e il Array ()
oggetto prototipo costruttore (Array.prototype
). In poche parole, myArray .__ proto__
(o myArray.constructor.prototype
) Riferimenti Array.prototype
.
prototipo
Catena è Object.prototype
Poiché la proprietà prototype è un oggetto, l'ultima fermata nella catena o nella ricerca del prototipo è Object.prototype
. Nel codice che segue, creo myArray
, che è una matrice vuota. Quindi tento di accedere a una proprietà di myArray
che non è stato ancora definito, impegnando la catena di ricerca prototipo. Il myArray
l'oggetto viene esaminato per la proprietà foo. Essendo assente, la proprietà è cercata a Array.prototype
, ma non è neanche lì. L'aspetto finale di JavaScript è quindi Object.prototype
. Perché non è definito in nessuno di questi tre oggetti, la proprietà è non definito
.
Esempio: sample123.html
Prendi nota che la catena si è fermata con Object.prototype
. L'ultimo posto che cercavamo era foo Object.prototype
.
Attento! Qualsiasi cosa aggiunta a Object.prototype verrà visualizzata in ciclo for in.
prototipo
Chain Restituisce la prima proprietà trovata trovata nella catenaCome la catena di portata, il prototipo
chain utilizzerà il primo valore che trova durante la ricerca della catena.
Modifica dell'esempio di codice precedente, se abbiamo aggiunto lo stesso valore a Object.prototype
e Array.prototype
oggetti, e quindi ha tentato di accedere a un valore su un'istanza di array, il valore restituito sarebbe da Array.prototype
oggetto.
Esempio: sample124.html
In questo esempio, il valore di foo a Array.prototype.foo
è ombreggiare, o mascherare, il foo
valore trovato a Object.prototype.foo
. Ricorda che la ricerca termina quando la proprietà viene trovata nella catena, anche se lo stesso nome di proprietà viene utilizzato anche più in alto nella catena.
prototipo
La proprietà con un nuovo oggetto rimuove la proprietà del costruttore di defaultÈ possibile sostituire il valore predefinito di a prototipo
proprietà con un nuovo valore. Tuttavia, così facendo eliminerà la proprietà predefinita del costruttore trovata nel "pre-made" prototipo
oggetto a meno che non ne specifichi manualmente uno.
Nel codice che segue, creiamo a foo
funzione di costruzione, sostituire il prototipo
proprietà con un nuovo oggetto vuoto e verificare che la proprietà del costruttore sia interrotta (ora fa riferimento a quella meno utile Oggetto
prototipo).
Esempio: sample125.html
Se si intende sostituire l'impostazione predefinita prototipo
proprietà (in comune con alcuni pattern JS OOP) impostata da JavaScript, è necessario collegare di nuovo una proprietà del costruttore che fa riferimento alla funzione del costruttore. Nel seguente esempio, modifichiamo il nostro codice precedente in modo che il costruttore
la proprietà fornirà nuovamente un riferimento alla corretta funzione di costruzione.
Esempio: sample126.html
prototipo
Otterrà sempre gli ultimi valoriLa proprietà prototype è dinamica nel senso che le istanze otterranno sempre l'ultimo valore dal prototipo indipendentemente da quando è stato istanziato, modificato o aggiunto. Nel codice che segue, creiamo a foo
costruttore, aggiungi la proprietà X
al prototipo
, e quindi creare un'istanza di Foo ()
di nome FooInstance
. Successivamente, registriamo il valore di X
. Quindi aggiorniamo il valore di prototipo di x e lo registriamo nuovamente per scoprire che la nostra istanza ha accesso all'ultimo valore trovato nel file prototipo
oggetto.
Esempio: sample127.html
Dato il funzionamento della catena di ricerca, questo comportamento non dovrebbe essere così sorprendente. Se ti stai chiedendo, questo funziona allo stesso modo indipendentemente dal fatto che tu usi l'impostazione predefinita prototipo
oggetto o ignorarlo con il tuo. Nel prossimo esempio, sostituisco il valore predefinito prototipo
oggetto di dimostrare questo fatto.
Esempio: sample128.html
prototipo
La proprietà con un nuovo oggetto non aggiorna le istanze precedentiPotresti pensare di poter sostituire il prototipo
proprietà interamente in qualsiasi momento e che tutte le istanze saranno aggiornate, ma questo non è corretto. Quando crei un'istanza, quell'istanza sarà legata a prototipo
quello era stato coniato al momento dell'istanziazione. Fornire un nuovo oggetto come la proprietà del prototipo non aggiorna la connessione tra istanze già create e la nuova prototipo
.
Ma ricorda, come ho affermato in precedenza, che puoi aggiornare o aggiungere all'originale creato prototipo
oggetto e quei valori rimangono collegati alle prime istanze.
Esempio: sample129.html
L'idea chiave da portare via qui è che un prototipo di oggetti non dovrebbe essere sostituito con un nuovo oggetto una volta che inizi a creare istanze. In questo modo, le istanze avranno un collegamento a diversi prototipi.
prototipo
Ereditarietà come costruttori nativiSi spera che a questo punto dell'articolo si stia affondando nel modo in cui lo stesso JavaScript sfrutta il prototipo
proprietà per eredità (Array.prototype
). Questo stesso modello può essere sfruttato durante la creazione di funzioni di costruzione non native e definite dall'utente. Nel seguente esempio, prendiamo il classico Persona
oggetto e imitare il modello che JavaScript utilizza per l'ereditarietà.
Esempio: sample130.html
In questo codice, a Persona()
viene creata la funzione di costruzione. Quindi aggiungiamo proprietà al prototipo
proprietà di Persona()
, che può essere ereditato da tutte le istanze. Chiaramente, puoi sfruttare la catena di prototipi nel tuo codice nello stesso modo in cui JavaScript lo sfrutta per l'ereditarietà di oggetti nativi.
Come buon esempio di come si può sfruttare questo, è possibile creare una funzione di costruzione le cui istanze ereditano il file gambe
e braccia
proprietà se non vengono fornite come parametri. Nel seguente esempio, se il Persona()
costruttore viene inviato parametri, i parametri vengono utilizzati come proprietà di istanza, ma se uno o più parametri non vengono forniti, vi è un fallback. Queste proprietà dell'istanza ombreggiano o mascherano le proprietà ereditate, offrendoti il meglio di entrambi i mondi.
Esempio: sample131.html
L'ereditarietà prototipale è stata concepita per consentire catene ereditarie che imitano i modelli di ereditarietà trovati nei tradizionali linguaggi di programmazione orientati agli oggetti. Affinché un oggetto erediti da un altro oggetto in JavaScript, tutto ciò che devi fare è istanziare un'istanza dell'oggetto da cui vuoi ereditare e assegnarla al prototipo
proprietà dell'oggetto che sta eseguendo l'ereditarietà.
Nell'esempio di codice che segue, capocuoco
oggetti (cody
) ereditato da Persona()
. Ciò significa che se una proprietà non viene trovata in a capocuoco
oggetto, verrà quindi cercato sul prototipo della funzione che ha creato Persona()
oggetti. Per cablare l'eredità, tutto ciò che devi fare è istanziare un'istanza di Persona()
come valore per Chef.prototype
(Chef.prototype = new Person ();
).
Esempio: sample132.html
Tutto ciò che abbiamo fatto in questo esempio è stato sfruttare un sistema che era già in atto con gli oggetti nativi. Considera che Persona()
non è diverso dal default Oggetto()
valore per le proprietà del prototipo. In altre parole, questo è esattamente ciò che accade quando una proprietà prototipo, contenente il suo predefinito vuoto Oggetto()
valore, guarda al prototipo della funzione di costruzione creata (Object.prototype
) per proprietà ereditate.