Object.setPrototypeOf()

par 2 contributeurs :

Cette fonction fait partie du standard ECMAScript 2015 (ES6)
Cette technologie a été finalisée mais il est préférable de consulter le tableau de compatibilité pour connaître l'état de l'implémentation dans les différents navigateurs.

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 obtimales, é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).

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 du dernier brouillon (draft) du standard ECMAScript 6. 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 :

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 === "number" || typeof oProto === "boolean") {
   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 Symbol () {
  this.isSymbol = "yes";
}

var nPrime = 17;

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

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

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 Statut Commentaires
ECMAScript 2015 (6th Edition, ECMA-262)
La définition de 'Object.setProtoypeOf' dans cette spécification.
Standard Définition initiale.

Compatibilité des navigateurs

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

Voir aussi

Étiquettes et contributeurs liés au document

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