Recherche…
Prototype de fonction standard
Commencez par définir une fonction Foo
que nous utiliserons comme constructeur.
function Foo (){}
En éditant Foo.prototype
, nous pouvons définir des propriétés et des méthodes qui seront partagées par toutes les instances de Foo
.
Foo.prototype.bar = function() {
return 'I am bar';
};
Nous pouvons alors créer une instance en utilisant le new
mot-clé et appeler la méthode.
var foo = new Foo();
console.log(foo.bar()); // logs `I am bar`
Différence entre Object.key et Object.prototype.key
Contrairement aux langages comme Python, les propriétés statiques de la fonction constructeur ne sont pas héritées des instances. Les instances n'héritent que de leur prototype, qui hérite du prototype du type parent. Les propriétés statiques ne sont jamais héritées.
function Foo() {};
Foo.style = 'bold';
var foo = new Foo();
console.log(Foo.style); // 'bold'
console.log(foo.style); // undefined
Foo.prototype.style = 'italic';
console.log(Foo.style); // 'bold'
console.log(foo.style); // 'italic'
Nouvel objet du prototype
En JavaScript, tout objet peut être le prototype d'un autre. Lorsqu'un objet est créé en tant que prototype d'un autre, il hérite de toutes les propriétés de son parent.
var proto = { foo: "foo", bar: () => this.foo };
var obj = Object.create(proto);
console.log(obj.foo);
console.log(obj.bar());
Sortie de la console:
> "foo"
> "foo"
REMARQUE Object.create
est disponible à partir d'ECMAScript 5, mais voici un polyfill si vous avez besoin du support pour ECMAScript 3
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}
Object.create ()
La méthode Object.create () crée un nouvel objet avec l'objet prototype et les propriétés spécifiés.
Syntaxe: Object.create(proto[, propertiesObject])
Paramètres :
- proto (objet qui devrait être le prototype de l'objet nouvellement créé)
- propertiesObject (Facultatif. Si spécifié et non indéfini, objet dont les propriétés propres énumérables (c'est-à-dire les propriétés définies sur lui-même et propriétés non énumérables le long de sa chaîne prototype) spécifient des descripteurs de propriétés à ajouter à l'objet nouvellement créé noms de propriétés: ces propriétés correspondent au second argument de Object.defineProperties ().)
Valeur de retour
Un nouvel objet avec l'objet prototype et les propriétés spécifiés.
Des exceptions
Une exception TypeError si le paramètre proto n'est pas null ou un objet.
Héritage prototypique
Supposons que nous ayons un objet simple appelé prototype
:
var prototype = { foo: 'foo', bar: function () { return this.foo; } };
Maintenant, nous voulons un autre objet appelé obj
qui hérite du prototype
, ce qui revient à dire que le prototype
est le prototype de obj
var obj = Object.create(prototype);
Maintenant, toutes les propriétés et méthodes du prototype
seront disponibles pour obj
console.log(obj.foo);
console.log(obj.bar());
Sortie de la console
"foo"
"foo"
L'héritage prototypal se fait par des références d'objet en interne et les objets sont complètement mutables. Cela signifie que tout changement effectué sur un prototype affectera immédiatement tous les autres objets dont le prototype est le prototype.
prototype.foo = "bar";
console.log(obj.foo);
Sortie de la console
"bar"
Object.prototype
est le prototype de chaque objet, il est donc fortement recommandé de ne pas jouer avec, en particulier si vous utilisez une bibliothèque tierce, mais nous pouvons en jouer un peu.
Object.prototype.breakingLibraries = 'foo';
console.log(obj.breakingLibraries);
console.log(prototype.breakingLibraries);
Sortie de la console
"foo"
"foo"
Fait amusant, j'ai utilisé la console du navigateur pour créer ces exemples et briser cette page en ajoutant cette propriété de breakingLibraries
.
Héritage pseudo-classique
C'est une émulation de l'héritage classique utilisant l' héritage prototypique qui montre à quel point les prototypes sont puissants. Il a été fait pour rendre le langage plus attrayant pour les programmeurs venant d'autres langues.
REMARQUE IMPORTANTE : depuis ES6, il n’est pas logique d’utiliser un héritage pseudo-calssical car le langage simule des classes conventionnelles . Si vous n'utilisez pas ES6, vous devriez le faire . Si vous souhaitez toujours utiliser le modèle d'héritage classique et que vous vous trouvez dans un environnement ECMAScript 5 ou inférieur, alors le pseudo-classique est votre meilleur pari.
Une "classe" est juste une fonction faite pour être appelée avec le new
opérande et utilisée comme constructeur.
function Foo(id, name) {
this.id = id;
this.name = name;
}
var foo = new Foo(1, 'foo');
console.log(foo.id);
Sortie de la console
1
foo est une instance de Foo. La convention de codage JavaScript indique que si une fonction commence par une majuscule, elle peut être appelée en tant que constructeur (avec le new
opérande).
Pour ajouter des propriétés ou des méthodes à la "classe", vous devez les ajouter à son prototype, qui se trouve dans la propriété prototype
du constructeur.
Foo.prototype.bar = 'bar';
console.log(foo.bar);
Sortie de la console
bar
En fait, ce que Foo fait en tant que "constructeur" consiste à créer des objets avec Foo.prototype
comme prototype.
Vous pouvez trouver une référence à son constructeur sur chaque objet
console.log(foo.constructor);
fonction Foo (id, name) {...
console.log({ }.constructor);
function Object () {[code natif]}
Et aussi vérifier si un objet est une instance d'une classe donnée avec l'opérateur instanceof
console.log(foo instanceof Foo);
vrai
console.log(foo instaceof Object);
vrai
Définition du prototype d'un objet
Avec ES5 +, la fonction Object.create
peut être utilisée pour créer un objet avec tout autre objet comme prototype.
const anyObj = {
hello() {
console.log(`this.foo is ${this.foo}`);
},
};
let objWithProto = Object.create(anyObj);
objWithProto.foo = 'bar';
objWithProto.hello(); // "this.foo is bar"
Pour créer explicitement un objet sans prototype, utilisez null
comme prototype. Cela signifie que l'objet n'héritera pas non plus d' Object.prototype
et qu'il est utile pour les objets utilisés pour vérifier les dictionnaires d'existence, par exemple
let objInheritingObject = {};
let objInheritingNull = Object.create(null);
'toString' in objInheritingObject; // true
'toString' in objInheritingNull ; // false
A partir d'ES6, le prototype d'un objet existant peut être modifié à l'aide d' Object.setPrototypeOf
, par exemple
let obj = Object.create({foo: 'foo'});
obj = Object.setPrototypeOf(obj, {bar: 'bar'});
obj.foo; // undefined
obj.bar; // "bar"
Cela peut se faire presque n'importe où, y compris sur this
objet ou dans un constructeur.
Remarque: Ce processus est très lent dans les navigateurs actuels et devrait être utilisé avec modération, essayez plutôt de créer l'objet avec le prototype souhaité.
Avant ES5, le seul moyen de créer un objet avec un prototype défini manuellement était de le construire avec un new
, par exemple
var proto = {fizz: 'buzz'};
function ConstructMyObj() {}
ConstructMyObj.prototype = proto;
var objWithProto = new ConstructMyObj();
objWithProto.fizz; // "buzz"
Ce comportement est suffisamment proche de Object.create
pour qu'il soit possible d'écrire un polyfill.