EDIT Février 2012: la réponse ci-dessous n'est plus exacte. __proto__ est ajouté à ECMAScript 6 en tant que "normatif facultatif", ce qui signifie qu'il n'est pas nécessaire de l'implémenter, mais si c'est le cas, il doit suivre l'ensemble de règles donné. Ceci n'est actuellement pas résolu, mais au moins, cela fera officiellement partie des spécifications de JavaScript.
Cette question est beaucoup plus compliquée qu'il n'y paraît à première vue, et au-delà de la rémunération de la plupart des gens en ce qui concerne la connaissance des internes Javascript.
La prototype
propriété d'un objet est utilisée lors de la création de nouveaux objets enfants de cet objet. Le changer ne se reflète pas dans l'objet lui-même, mais est plutôt reflété lorsque cet objet est utilisé comme constructeur pour d'autres objets, et n'a aucune utilité pour changer le prototype d'un objet existant.
function myFactory(){};
myFactory.prototype = someOtherObject;
var newChild = new myFactory;
newChild.__proto__ === myFactory.prototype === someOtherObject; //true
Les objets ont une propriété interne [[prototype]] qui pointe vers le prototype actuel. La façon dont cela fonctionne est que chaque fois qu'une propriété sur un objet est appelée, elle commencera à l'objet, puis remontera dans la chaîne [[prototype]] jusqu'à ce qu'elle trouve une correspondance, ou échoue, après le prototype de l'objet racine. C'est ainsi que Javascript permet la construction et la modification d'objets à l'exécution; il a un plan pour rechercher ce dont il a besoin.
La __proto__
propriété existe dans certaines implémentations (beaucoup maintenant): toute implémentation de Mozilla, toutes les webkit que je connais, quelques autres. Cette propriété pointe vers la propriété interne [[prototype]] et permet de modifier post-création sur les objets. Toutes les propriétés et fonctions basculeront instantanément pour correspondre au prototype en raison de cette recherche en chaîne.
Cette fonctionnalité, bien qu'étant normalisée actuellement, n'est toujours pas une partie obligatoire de JavaScript, et dans les langages qui la supportent, elle a une forte probabilité de faire tomber votre code dans la catégorie «non optimisé». Les moteurs JS doivent faire de leur mieux pour classer le code, en particulier le code "chaud" auquel on accède très souvent, et si vous faites quelque chose d'extraordinaire comme la modification __proto__
, ils n'optimiseront pas du tout votre code.
Cet article https://bugzilla.mozilla.org/show_bug.cgi?id=607863 traite spécifiquement des implémentations actuelles __proto__
et des différences entre elles. Chaque implémentation le fait différemment, car c'est un problème difficile et non résolu. Tout en Javascript est mutable, sauf a.) La syntaxe b.) Les objets hôtes (le DOM existe techniquement en dehors de Javascript) et c.) __proto__
. Le reste est entièrement entre les mains de vous et de tous les autres développeurs, vous pouvez donc voir pourquoi cela __proto__
ressort comme un pouce endolori.
Il y a une chose qui __proto__
permet que cela soit autrement impossible à faire: la désignation d'un prototype d'objets à l'exécution séparé de son constructeur. Il s'agit d'un cas d'utilisation important et l'une des principales raisons pour lesquelles il __proto__
n'est pas déjà mort. C'est suffisamment important pour que cela ait été un point de discussion sérieux dans la formulation d'Harmony, ou bientôt connu sous le nom d'ECMAScript 6. La possibilité de spécifier le prototype d'un objet lors de la création fera partie de la prochaine version de Javascript et ce sera la cloche indiquant __proto__
les jours est formellement numérotée.
À court terme, vous pouvez l'utiliser __proto__
si vous ciblez les navigateurs qui le prennent en charge (pas IE, et aucun IE ne le fera jamais). Il est probable que cela fonctionnera dans Webkit et moz pendant les 10 prochaines années, car ES6 ne sera pas finalisé avant 2013.
Brendan Eich - re: Approche des nouvelles méthodes Object dans ES5 :
Désolé, ... mais paramétrable __proto__
, mis à part le cas d'utilisation de l'initialiseur d'objet (c'est-à-dire sur un nouvel objet non encore accessible, analogue à Object.create d'ES5), est une idée terrible. J'écris ceci après avoir conçu et implémenté configurable il y a __proto__
plus de 12 ans.
... le manque de stratification est un problème (considérez les données JSON avec une clé "__proto__"
). Et pire, la mutabilité signifie que les implémentations doivent vérifier les chaînes prototypes cycliques afin d'éviter les boucles. [des vérifications constantes de la récursivité infinie sont requises]
Enfin, muter __proto__
sur un objet existant peut casser des méthodes non génériques dans le nouvel objet prototype, qui ne peuvent pas fonctionner sur l'objet récepteur (direct) dont il __proto__
est défini. C'est simplement une mauvaise pratique, une forme de confusion de type intentionnelle, en général.