Prima di tutto, ricorda che JavaScript è principalmente un linguaggio prototipo , piuttosto che un linguaggio di classe 1 . Foo
non è una classe, è una funzione, che è un oggetto. Puoi creare un'istanza di un oggetto da quella funzione usando la new
parola chiave che ti permetterà di creare qualcosa di simile a una classe in un linguaggio OOP standard.
Suggerirei di ignorare la __proto__
maggior parte delle volte perché ha un supporto scarso tra i browser e invece di concentrarmi sull'apprendimento di come prototype
funziona.
Se si dispone di un'istanza di un oggetto creata da una funzione 2 e si accede a uno dei suoi membri (metodi, attributi, proprietà, costanti, ecc.) In qualsiasi modo, l'accesso scorrerà lungo la gerarchia del prototipo fino a quando non ( membro o (b) non trova un altro prototipo.
La gerarchia inizia sull'oggetto che è stato chiamato e quindi cerca il suo oggetto prototipo. Se l'oggetto prototipo ha un prototipo, viene ripetuto, se non esiste alcun prototipo, undefined
viene restituito.
Per esempio:
foo = {bar: 'baz'};
console.log(foo.bar); // logs "baz"
foo = {};
console.log(foo.bar); // logs undefined
function Foo(){}
Foo.prototype = {bar: 'baz'};
f = new Foo();
console.log(f.bar);
// logs "baz" because the object f doesn't have an attribute "bar"
// so it checks the prototype
f.bar = 'buzz';
console.log( f.bar ); // logs "buzz" because f has an attribute "bar" set
Mi sembra che tu abbia almeno in qualche modo capito già queste parti "di base", ma devo renderle esplicite solo per essere sicuri.
In JavaScript, tutto è un oggetto 3 .
tutto è un oggetto.
function Foo(){}
non definisce solo una nuova funzione, ma definisce un nuovo oggetto funzione a cui è possibile accedere utilizzando Foo
.
Questo è il motivo per cui è possibile accedere Foo
al prototipo con Foo.prototype
.
Quello che puoi anche fare è impostare più funzioni su Foo
:
Foo.talk = function () {
alert('hello world!');
};
È possibile accedere a questa nuova funzione utilizzando:
Foo.talk();
Spero ormai che tu stia notando una somiglianza tra le funzioni su un oggetto funzione e un metodo statico.
Pensa f = new Foo();
alla creazione di un'istanza di classe, Foo.prototype.bar = function(){...}
alla definizione di un metodo condiviso per la classe e Foo.baz = function(){...}
alla definizione di un metodo statico pubblico per la classe.
ECMAScript 2015 ha introdotto una varietà di zucchero sintattico per questo tipo di dichiarazioni per renderle più semplici da implementare e allo stesso tempo più facili da leggere. L'esempio precedente può quindi essere scritto come:
class Foo {
bar() {...}
static baz() {...}
}
che consente bar
di essere chiamato come:
const f = new Foo()
f.bar()
e baz
di essere chiamato come:
Foo.baz()
1: class
era una "Parola riservata futura" nella specifica ECMAScript 5 , ma ES6 introduce la possibilità di definire le classi usando la class
parola chiave.
2: essenzialmente un'istanza di classe creata da un costruttore, ma ci sono molte differenze sfumate che non voglio fuorviare
3: valori primitivi -che comprendono undefined
, null
, booleani, numeri e stringhe-ITA oggetti tecnicamente perché sono implementazioni linguaggio di basso livello. Booleani, numeri e stringhe interagiscono ancora con la catena del prototipo come se fossero oggetti, quindi ai fini di questa risposta, è più facile considerarli "oggetti" anche se non del tutto.
Foo.talk = function ...