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


```js
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
--------


```js
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 :


```js
// 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 :


```js
/\*\*
 \*\*\* 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


```js
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


```js
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


```js
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
--------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-object.setprototypeof |

Compatibilité des navigateurs
-----------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Voir aussi
----------

* `Reflect.setPrototypeOf()`
* `Object.prototype.isPrototypeOf()`
* `Object.getPrototypeOf()`
* `Object.prototype.__proto__`