MDN’s new design is in Beta! A sneak peek: https://blog.mozilla.org/opendesign/mdns-new-design-beta/

Object.setPrototypeOf()

Attention : Étant donnée la façon dont la plupart des moteurs JavaScript optimisent les performances, modifier le [[Prototype]] d'un objet est une opération lente pour chaque navigateur et moteur JavaScript. Les impacts liés aux performances sur ce point sont vastes et subtiles : ils concernent pas uniquement le temps passé à effectuer Object.setPrototypeOf, mais peuvent concerner n'importe quel code pour n'importe quel objet dont [[Prototype]] a été modifié. Si vous souhaitez obtenir des performances optimales, évitez de modifier le [[Prototype]] d'un objet. À la place, il est conseillé de créer un objet avec le prototype voulu en utilisant Object.create()

La méthode Object.setPrototypeOf() définit le prototype (autrement dit la propriété interne [[Prototype]]) d'un objet donné avec un autre objet ou null.

Syntaxe

Object.setPrototypeOf(obj, prototype);

Paramètres

obj
L'objet dont on souhaite définir le prototype.
prototype
Le nouveau prototype de l'objet (un objet ou null).

Valeur de retour

L'objet sur lequel on a défini le prototype.

Description

Cette méthode renvoie une exception TypeError si l'objet dont on souhaite modifier le [[Prototype]] est non-extensible selon Object.isExtensible.  Cette méthode ne fait rien si le paramètre prototype n'est ni un objet ni null (par exemple : un nombre, une chaîne, un booléen ou undefined).  Dans les autres cas, cette méthode substitue le [[Prototype]] de obj avec un nouvel objet.

Object.setPrototypeOf() fait partie de la spécification ECMAScript 2015. L'utilisation de cette méthode est considérée comme la façon correcte pour modifier le prototype d'un objet (contrairement à la propriété Object.prototype.__proto__ plus controversée).

Exemples

var dict = Object.setPrototypeOf({}, null);

Prothèse d'émulation (polyfill)

En utilisant la propriété Object.prototype.__proto__, on peut définir Object.setPrototypeOf si elle n'est pas disponible :

// Cette prothèse ne fonctionne pas pour IE
Object.setPrototypeOf = Object.setPrototypeOf || function (obj, proto) {
  obj.__proto__ = proto;
  return obj; 
}

Ajouter une chaîne de prototypes à un objet

En combinant Object.getPrototypeOf() et Object.prototype.__proto__ on peut ajouter une chaîne de prototypes au nouveau prototype d'un objet :

/**
*** Object.setPrototypeOf(@object, @prototype)
* Change le prototype d'une instance
*
**/

Object.setPrototypeOf = function (oInstance, oProto) {
  oInstance.__proto__ = oProto;
  return oInstance;
};

/**
*** Object.appendChain(@object, @prototype)
*
* Ajoute le premier prototype non-natif d'une chaîne au nouveau prototype.
* Renvoie @object (si c'est une valeur primitive, elle sera transformée
* en objet).
*
*** Object.appendChain(@object [, "@arg_name_1", "@arg_name_2", "@arg_name_3", "..."], "@function_body")
*** Object.appendChain(@object [, "@arg_name_1, @arg_name_2, @arg_name_3, ..."], "@function_body")
*
* Ajoute le premier prototype non-natif d'une chaîne à l'objet Function.prototype
* puis ajoute new Function(["@arg"(s)], "@function_body") à cette chaîne.
* Renvoie la fonction.
*
**/

Object.appendChain = function (oChain, oProto) {
  if (arguments.length < 2) { 
    throw new TypeError("Object.appendChain - Pas suffisamment d'arguments");
  }
  if (typeof oProto !== 'object' && typeof oProto !== 'string') {
   throw new TypeError("le deuxième argument de Object.appendChain doit être un objet ou une chaîne");
  }

  var oNewProto = oProto, oReturn = o2nd = oLast = oChain instanceof this ? oChain : new oChain.constructor(oChain);

  for (var o1st = this.getPrototypeOf(o2nd); o1st !== Object.prototype && o1st !== Function.prototype; o1st = this.getPrototypeOf(o2nd)) {
    o2nd = o1st;
  }

  if (oProto.constructor === String) {
    oNewProto = Function.prototype;
    oReturn = Function.apply(null, Array.prototype.slice.call(arguments, 1));
    this.setPrototypeOf(oReturn, oLast);
  }

  this.setPrototypeOf(o2nd, oNewProto);
  return oReturn;
}

Utilisation

Ajouter une chaîne de prototypes à un prototype

function Mammifère () {
  this.isMammifère = "oui";
}

function EspèceMammifère (sEspèceMammifère) {
  this.espèce = sEspèceMammifère;
}

EspèceMammifère.prototype = new Mammifère();
EspèceMammifère.prototype.constructor = EspèceMammifère;

var oChat = new EspèceMammifère("Felis");

console.log(oChat.isMammifère); // "oui"

function Animal () {
  this.respire = "oui";
}

Object.appendChain(oChat, new Animal());

console.log(oChat.respire); // "oui"

Deuxième exemple : Transformer une valeur primitive en une instance de son constructeur et ajouter sa chaîne à un prototype

function MySymbol () {
  this.isSymbol = "yes";
}

var nPrime = 17;

console.log(typeof nPrime); // "number"

var oPrime = Object.appendChain(nPrime, new MySymbol());

console.log(oPrime); // "17"
console.log(oPrime.isSymbol); // "yes"
console.log(typeof oPrime); // "object"

Troisième exemple : Ajouter une chaîne de prototypes à l'objet Function.prototype object et ajouter une nouvelle fonction à cette chaîne

function Personne (sNom) {
  this.identité = sNom;
}

var george = Object.appendChain(new Person("George"), 
                                "console.log(\"Salut !!\");");

console.log(george.identité); // "George"
george(); // "Salut !!"

Spécifications

Spécification État Commentaires
ECMAScript 2015 (6th Edition, ECMA-262)
La définition de 'Object.setProtoypeOf' dans cette spécification.
Standard Définition initiale.
ECMAScript Latest Draft (ECMA-262)
La définition de 'Object.setProtoypeOf' dans cette spécification.
Projet  

Compatibilité des navigateurs

Fonctionnalité Chrome Firefox (Gecko) Edge Internet Explorer Opera Safari
Support simple 34 31 (31) (Oui) 11 (Oui) 9
Fonctionnalité Android Chrome for Android Firefox Mobile (Gecko) Edge IE Mobile Opera Mobile Safari Mobile
Support simple Pas de support Pas de support 31.0 (31) (Oui) ? Pas de support 9

Voir aussi

Étiquettes et contributeurs liés au document

 Contributeurs à cette page : SphinxKnight, 42void, teoli
 Dernière mise à jour par : SphinxKnight,