Cosa significa che Javascript è un linguaggio basato su prototipo?


Risposte:


291

L'eredità prototipale è una forma di riutilizzo del codice orientato agli oggetti . Javascript è uno dei pochi linguaggi orientati agli oggetti [mainstream] ad usare l'ereditarietà prototipale. Quasi tutti gli altri linguaggi orientati agli oggetti sono classici.

In eredità classica , il programmatore scrive una classe, che definisce un oggetto. Più oggetti possono essere istanziati dalla stessa classe, quindi hai un codice in un posto che descrive diversi oggetti nel tuo programma. Le classi possono quindi essere organizzate in una gerarchia, favorendo il riutilizzo del codice. Codice più generale viene archiviato in una classe di livello superiore, da cui ereditano le classi di livello inferiore. Ciò significa che un oggetto condivide il codice con altri oggetti della stessa classe, nonché con le sue classi principali.

Nella forma di ereditarietà del prototipo , gli oggetti ereditano direttamente da altri oggetti. Tutti gli affari sulle lezioni vanno via. Se vuoi un oggetto, scrivi semplicemente un oggetto. Ma il riutilizzo del codice è ancora una cosa preziosa, quindi gli oggetti possono essere collegati insieme in una gerarchia. In JavaScript, ogni oggetto ha un collegamento segreto all'oggetto che lo ha creato, formando una catena. Quando viene richiesto a un oggetto una proprietà che non ha, verrà chiesto al suo oggetto genitore ... continuamente su per la catena fino a quando non viene trovata la proprietà o fino al raggiungimento dell'oggetto root.

Ogni funzione in JavaScript (che sono oggetti stessi) in realtà ha un membro chiamato "prototipo", che è responsabile di fornire valori quando viene richiesto un oggetto per loro. Avere questo membro consente al meccanismo di costruzione (tramite il quale gli oggetti sono costruiti da funzioni) di funzionare. L'aggiunta di una proprietà al prototipo di un oggetto funzione lo renderà disponibile per l'oggetto costruito, così come per tutti gli oggetti che ereditano da esso.

vantaggi

Potrebbe non esserci una regola rigida sul perché l'ereditarietà prototipale sia una forma vantaggiosa di riutilizzo del codice. Il riutilizzo del codice stesso è vantaggioso e l'ereditarietà prototipale è un modo ragionevole di procedere. Si potrebbe sostenere che l'ereditarietà prototipale sia un modello abbastanza semplice di riutilizzo del codice e che il codice possa essere pesantemente riutilizzato in modo diretto . Ma anche le lingue classiche sono certamente in grado di farlo.

Sidenote: @Andrew Hedges sottolinea che esistono in realtà molti linguaggi prototipali. Vale la pena notare che questi altri esistono, ma vale anche la pena notare che nessuno di loro è qualcosa di simile al mainstream. NewtonScript sembrò avere una certa trazione per un po ', ma morì con la sua piattaforma. È anche possibile estendere alcuni linguaggi moderni in modi che aggiungono capacità prototipali.


9
Ehi Kelly. Mentre JavaScript è di gran lunga il linguaggio prototipo più popolare, ce ne sono molti altri: en.wikipedia.org/wiki/Prototype-based_programming#Languages
Andrew Hedges

2
Ehi Andrew. Buon punto. Avrei dovuto essere più chiaro. Ne prenderò nota.
Keparo,

3
Si prega di leggere anche questo developer.mozilla.org/it/JavaScript/Guide/…
pramodc84

1
+1 per un'ottima risposta. Un piccolo commento: per me l'eredità classica sembra più "diretta" del prototipo. In effetti, vedo davvero l'oggetto prototipo come un semplice collegamento (con altri oggetti), mentre in una OOP compilata considero la classe base "ereditata direttamente". Pertanto, gli oggetti prototipo sono concatenati piuttosto che ereditati (l'eredità è in qualche modo falsata). qualche idea?
Prigioniero ZERO,

3
@PrisonerZERO: direi che l'eredità prototipale è più diretta del classico. Invece dell'oggetto B che punta a una classe che eredita dalla classe a cui punta l'oggetto A, punta direttamente sull'oggetto A e dice "Sono proprio come quell'oggetto, tranne ...". La cosa importante dell'ereditarietà prototipale, e la cosa che sembra più difficile da interiorizzare per la maggior parte delle persone, è che non distingue i casi dai tipi. Ogni oggetto è sia un tipo che un'istanza. Le distinzioni tra i due sono artificiali e intenzionali e di solito sono un sintomo di essere bloccati in una mentalità orientata alla classe.
cHao,

54

Un linguaggio basato sui prototipi, non fa distinzione tra classi e oggetti: ha semplicemente oggetti. Un linguaggio basato su prototipo ha la nozione di oggetto prototipico, un oggetto usato come modello da cui ottenere le proprietà iniziali per un nuovo oggetto. Qualsiasi oggetto può specificare le proprie proprietà, sia quando lo si crea che in fase di esecuzione. Inoltre, qualsiasi oggetto può essere associato come prototipo per un altro oggetto , consentendo al secondo oggetto di condividere le proprietà del primo oggetto.


6
Una spiegazione molto buona, ma un po 'fuorviante con il commento sul "modello per le proprietà iniziali". Se si modifica il prototipo DOPO aver creato un'istanza di un oggetto, quell'oggetto riceve comunque quelle funzioni.
Nickf

32

La programmazione basata su prototipi è uno stile di programmazione orientata agli oggetti in cui le classi non sono presenti e il riutilizzo del comportamento (o ereditarietà in linguaggi basati su classi) viene eseguito clonando oggetti esistenti che fungono da prototipi.


Ti senti ancora così? Perché se è così, questa è la prima spiegazione per fare semplicemente "clic" in modo solido con me.
Chazt3n,

11

Il vantaggio / svantaggio è che possiamo creare nuovi tipi di oggetti in fase di esecuzione senza la necessità di definire le classi (codice statico). Come la maggior parte delle funzionalità spetta allo sviluppatore trasformarlo in un vantaggio / svantaggio.

Sopra è possibile perché gli oggetti sono essenzialmente funzioni nello script java (anche chiusure).


Gli oggetti dinamici sono un vantaggio di javascript, ma non sono realmente correlati al fatto che javascript sia un linguaggio prototipo o funzionale. In molti linguaggi classici è possibile creare oggetti dinamici in fase di esecuzione. Anche le chiusure sono in qualche modo indipendenti.
Keparo,

2
Le classi non sono necessariamente un codice statico: dai un'occhiata a Python, in cui le classi sono oggetti stessi e sono costruite con metaclasse che sono anche oggetti.
Tomasz Zieliński,

6

Invece di dichiarare una struttura di classe, puoi creare oggetti dello stesso tipo e aggiungerli alla loro definizione ogni volta che vuoi usando il prototipo dell'oggetto. È più flessibile del normale modo di fare le cose.


6

Se si utilizzano semplicemente oggetti in fase di esecuzione anziché una classe durante la compilazione per creare nuovi oggetti, si apre la possibilità di estendere un oggetto senza conoscerne i dettagli. Certo, può diventare uno svantaggio abbastanza rapidamente a seconda dell'uso. Non faccio ipotesi sulla lingua qui, quindi è applicabile a lingue diverse da javascript che non sono così dinamiche.

myobject.prototype=unkownobject;
myobject.newproperty=1;

È possibile ottenere l'oggetto praticamente ovunque; il tuo codice, dalla rete, dal database, dal collegamento esterno e così via.

Nota che un linguaggio non deve implementare l'ereditarietà del prototipo come javascript. In javascript, un oggetto prototipo è semplicemente condiviso, così come le sue proprietà, tra gli eredi. L'alternativa è la copia di tutte le proprietà del prototipo nel nuovo oggetto. Ogni approccio ha i suoi punti di forza in diverse situazioni. Mi piace di più il secondo ma non è quello che fa JavaScript.


6

Dopo aver letto tutte le risposte questa è la conclusione

1) Eredità in cui gli oggetti sono ereditati direttamente da altri oggetti

2) Che non utilizza le classi

3) Chiamata anche programmazione basata su istanza o programmazione orientata ai prototipi senza classe

4) Il riutilizzo del comportamento viene eseguito clonando oggetti esistenti che fungono da prototipi

5) L'oggetto utilizzato come modello dal nuovo oggetto ottiene le proprietà iniziali

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.