Tout d'abord, rappelez-vous que JavaScript est principalement un langage prototypique , plutôt qu'un langage basé sur une classe 1 . Foo
n'est pas une classe, c'est une fonction, qui est un objet. Vous pouvez instancier un objet à partir de cette fonction en utilisant lenew
mot clé qui vous permettra de créer quelque chose de similaire à une classe dans un langage OOP standard.
Je suggérerais d'ignorer la __proto__
plupart du temps, car il ne prend pas en charge plusieurs navigateurs, et plutôt de se concentrer sur l'apprentissageprototype
fonctionnement.
Si vous avez une instance d'un objet créé à partir d'une fonction 2 et que vous accédez à l'un de ses membres (méthodes, attributs, propriétés, constantes, etc.) de quelque manière que ce soit, l'accès descendra dans la hiérarchie du prototype jusqu'à ce qu'il (a) trouve le membre, ou (b) ne trouve pas un autre prototype.
La hiérarchie commence sur l'objet appelé, puis recherche son objet prototype. Si l'objet prototype a un prototype, il se répète, si aucun prototype n'existe, undefined
est retourné.
Par exemple:
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
Il me semble que vous avez déjà au moins quelque peu compris ces parties "de base", mais je dois les rendre explicites juste pour être sûr.
En JavaScript, tout est un objet 3 .
tout est un objet.
function Foo(){}
ne définit pas seulement une nouvelle fonction, il définit un nouvel objet fonction accessible à l'aide de Foo
.
C'est pourquoi vous pouvez accéder Foo
au prototype de avec Foo.prototype
.
Vous pouvez également définir plus de fonctions sur Foo
:
Foo.talk = function () {
alert('hello world!');
};
Cette nouvelle fonction est accessible en utilisant:
Foo.talk();
J'espère que vous remarquez maintenant une similitude entre les fonctions d'un objet fonction et une méthode statique.
Pensez f = new Foo();
à créer une instance de classe, Foo.prototype.bar = function(){...}
à définir une méthode partagée pour la classe et Foo.baz = function(){...}
à définir une méthode statique publique pour la classe.
ECMAScript 2015 a introduit une variété de sucre syntaxique pour ces types de déclarations afin de les rendre plus simples à mettre en œuvre tout en étant plus faciles à lire. L'exemple précédent peut donc s'écrire:
class Foo {
bar() {...}
static baz() {...}
}
qui permet bar
d'être appelé comme:
const f = new Foo()
f.bar()
et baz
être appelé comme:
Foo.baz()
1: class
était un "futur mot réservé" dans la spécification ECMAScript 5 , mais ES6 introduit la possibilité de définir des classes à l'aide du class
mot - clé.
2: essentiellement une instance de classe créée par un constructeur, mais il existe de nombreuses différences nuancées que je ne veux pas vous induire en erreur
3: les valeurs primitives - qui incluent undefined
, les null
booléens, les nombres et les chaînes - ne sont pas techniquement des objets car ce sont des implémentations de langage de bas niveau. Les booléens, les nombres et les chaînes interagissent toujours avec la chaîne prototype comme s'ils étaient des objets, donc pour les besoins de cette réponse, il est plus facile de les considérer comme des "objets" même s'ils ne le sont pas tout à fait.
Foo.talk = function ...