Object.prototype.\_\_proto\_\_
==============================

**Obsolète:** Cette fonctionnalité a été supprimée des standards du Web. Bien que quelques navigateurs puissent encore la supporter, elle est en cours d'éradication. Ne l'utilisez ni dans d'anciens projets, ni dans de nouveaux. Les pages et applications Web l'utilisant peuvent cesser de fonctionner à tout moment.

**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 `obj.__proto__ = ...`, 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()`.

**Attention :** Bien que la propriété `Object.prototype.__proto__` soit déjà supportée dans la plupart des navigateurs à l'heure actuelle, son comportement n'a été standardisé que récemment avec la spécification ECMAScript 2015. Si vous avez besoin d'utiliser cette propriété dans des environnements antérieurs à ES2015, il est recommandé d'utiliser `Object.getPrototypeOf()`.

La propriété `__proto__` de `Object.prototype` (en-US) est une propriété accesseur (un couple de fonction avec un accesseur (*getter*) et un mutateur (*setter*)) qui expose le `[[Prototype]]` interne (qui est soit un objet, soit `null`) de l'objet courant.

L'utilisation de `__proto__` est sujet à controverse. Elle a été déconseillée par plusieurs personnes et n'avait jamais été incluse dans la spécification ECMAScript. Cependant, de nombreux navigateurs ont décidé de l'implémenter. À l'heure actuelle, la propriété `__proto__` a été standardisée avec la spécification ECMAScript 2015 et sera officiellement supportée à l'avenir. Une alternative à cette propriété peut être l'utilisation des méthodes `Object.getPrototypeOf`/`Reflect.getPrototypeOf` et `Object.setPrototypeOf`/`Reflect.setPrototypeOf`. Cependant, modifier le `[[Prototype]]` d'un objet est toujours une opération lente qui doit être évitée le plus possible pour des raisons de performances.

La propriété `__proto__` peut également être utilisée avec un littéral objet afin de définir le `[[Prototype]]` lors de la construction (ce qui en fait une alternative à `Object.create()`. Voir la page sur les initialisateurs d'objet.

Syntaxe
-------


```js
var proto = obj.__proto__;
```


**Note :** le nom de la propriété est composé de deux tirets bas, suivis de « proto », suivis par deux tirets bas (*underscores*)

Description
-----------

L'accesseur `__proto__` expose la valeur du `[[Prototype]]` interne d'un objet.

* Pour les objets créés via un littéral objet, cette valeur est `Object.prototype` (en-US).
* Pour les objet créés via un littéral de tableau, cette valeur est `Array.prototype`.
* Pour les fonctions, cette valeur est `Function.prototype`.
* Pour les objets créés en utilisant `new fun`, avec `fun` un des constructeurs natif de fonctions, fournis par JavaScript (`Array`, `Boolean`, `Date`, `Number`, `Object`, `String`, etc.), cette valeur est `fun.prototype`.
* Pour les objets créés en utilisant `new fun`, avec `fun` une function definie dans un script, cette valeur est la valeur de `fun.prototype` au moment où `new fun` est évaluée. (Ainsi, si on affecte une nouvelle valeur à `fun.prototype`, les instances crées précédemment conserveront leur `[[Prototype]]`, les objets créés par la suite bénéficieront de la nouvelle valeur pour leur `[[Prototype]]`.)

Le mutateur `__proto__` permet de changer le `[[Prototype]]` d'un objet. Cet objet doit être extensible selon `Object.isExtensible`, si ce n'est pas le cas, une exception `TypeError` sera renvoyée. La valeur fournie pour le nouveau prototype doit être un objet ou `null`. Toute autre valeur entraînera un échec silencieux.

Pour plus d'éléments sur le fonctionnement de l'héritage et des prototypes, voir la page sur l'héritage et les chaînes de prototypes.

Le propriété `__proto__` n'est qu'une propriété accesseur (composée d'une fonction accesseur (*getter*) et d'une fonction mutateur (*setter*)) pour `Object.prototype` (en-US). Si l'accès à `__proto__` consulte `Object.prototype` (en-US), on trouvera la propriété. Un accesseur qui ne consulte pas `Object.prototype` (en-US) ne pourra pas trouver le prototype. Si une propriété `__proto__` est trouvée avant que `Object.prototype` (en-US) ne soit consulté, cette propriété « cachera » `Object.prototype` (en-US).


```js
var aucunProto = Object.create(null);

console.log(typeof aucunProto.__proto__); // undefined
console.log(Object.getPrototypeOf(aucunProto)); // null

aucunProto.__proto__ = 17;

console.log(aucunProto.__proto__); // 17
console.log(Object.getPrototypeOf(aucunProto)); // null

var protoCaché = {};
Object.defineProperty(protoCaché, "\_\_proto\_\_", {
  value: 42,
  writable: true,
  configurable: true,
  enumerable: true,
});

console.log(protoCaché.__proto__); // 42
console.log(Object.getPrototypeOf(protoCaché) === Object.prototype); // true
```

Exemples
--------

Dans ce qui suit, on crée un nouvelle instance d'`Employé` et on teste si `__proto__` est bien le même objet que le prototype de son constructeur.

**Attention :** Les remarques données plus haut sur les atteintes à la performance restent valables pour ces exemples. Ces exemples permettent uniquement d'illustrer le fonctionnement de `__proto__`, ils ne font pas office de recommandations.


```js
// On déclare une fonction à utiliser comme constructeur
function Employé() {
  /\* on initialise l'instance \*/
}

// On crée une nouvelle instance d'Employé
var fred = new Employé();

// On teste l'équivalence
fred.__proto__ === Employé.prototype; // true
```


À cet instant, `fred` hérite de `Employé`. On peut toutefois changer ça en assignant un nouvel objet à `fred.__proto__` :


```js
// Assigner un nouvel objet à \_\_proto\_\_
fred.__proto__ = Object.prototype;
```


`fred` n'hérite plus de `Employé.prototype`, mais de `Object.prototype`. Il perd donc les propriétés héritées de `Employé.prototype`.

Cela n'est possible que pour les objets extensibles. La propriété `__proto__` d'un objet non-extensible ne peut pas être changée :


```js
var obj = {};
Object.preventExtensions(obj);

obj.__proto__ = {}; // renvoie une exception TypeError
```


On notera que même la propriété `__proto__` de `Object.prototype` peut être redéfinie tant que la chaîne de prototypes se termine par `null` :


```js
var b = {};

Object.prototype.__proto__ = Object.create(
  null, //[[Prototype]]
  {
    salut: {
      value: function () {
        console.log("salut");
      },
    },
  },
);

b.salut();
```


Si la propriété `__proto__` de `Object.prototype` (en-US) ne permet pas d'aboutir à `null` via la chaîne de prototypes, on a une chaîne cyclique et on doit avoir une exception `TypeError` "cyclic \_\_proto\_\_ value".

Spécifications
--------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-object.prototype.\_\_proto\_\_ |

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

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

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

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