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();
    };
}

Source: http://javascript.crockford.com/prototypal.html


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.

6

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

5

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
6

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é.

5

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.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow