2010-01-21 9 views
7

o.prototype = {...} ne fonctionne que si o est une fonction. Supposons que j'ai le code suivantPrototype JavaScript limité aux fonctions?

conf = { 
    a: 2, 
    b: 4 
}; 
conf.prototype = { 
    d: 16 
} 

de conf.a et conf.b est OK et renvoie des valeurs propres. Mais conf.d ne renvoie pas 16 plutôt il va indéfini. Y a-t-il une solution à craindre que la généralisation basée sur un prototype puisse aussi être appliquée sur ce type d'objets.

Répondre

21

Vous confondez la propriété prototype qui peut être utilisé sur Constructor Functions et la propriété interne [[Prototype]].

Tous les objets possèdent cette propriété interne [[Prototype]] et seul l'opérateur new lorsque vous l'appelez avec une fonction constructeur est autorisé à le définir (via l'opération interne [[Construct]]).

Si vous voulez avoir l'héritage prototypal avec des instances d'objets (sans utiliser les constructeurs), la technique de Crockford Object.create est ce que vous voulez (cette méthode fait maintenant partie du récemment approuvé ECMAScript 5e édition):

// Check if native implementation available 
if (typeof Object.create !== 'function') { 
    Object.create = function (o) { 
    function F() {} // empty constructor 
    F.prototype = o; // set base object as prototype 
    return new F(); // return empty object with right [[Prototype]] 
    }; 
} 

var confProto = { 
    d: 16 
}; 
var conf = Object.create(confProto); 
conf.a = 2; 
conf.b = 4; 

dans le code ci-dessus conf aura ses trois membres, mais seulement a et b volonté existe physiquement sur elle:

conf.hasOwnProperty('a'); // true 
conf.hasOwnProperty('b'); // true 
conf.hasOwnProperty('d'); // false 

Parce que d existe sur la conf [[Prototype]] (confProto).

Le property accessors, . et [] sont responsables de résoudre les propriétés à la recherche si nécessaire dans la chaîne de prototype (par la méthode interne [[Get]]).

+3

Pourriez être le descendant s'il vous plaît laisser un commentaire? Je cherche toujours à améliorer mes réponses :) – CMS

6

Il y a en fait deux types différents de « prototype » en JavaScript:

  1. One est le lien « caché » chaque objet a (nous allons utiliser [[Prototype]] pour représenter ce lien caché). Les objets littéraux par défaut ont leurs liens cachés pointant vers Object.prototype, les objets fonction ont leur lien caché pointant vers Function.prototype, et les tableaux pointent vers Array.prototype. Ces les prototypes de liens cachés ne sont pas associés aux propriétés avec le nom "prototype". Vous ne pouvez pas modifier ces liens cachés en ajoutant ou en modifiant o.prototype.
  2. Un autre est que tous les objets de fonction ont automatiquement une propriété spéciale nommée "prototype". Ceci est principalement pour l'utilisation du modèle d'invocation de constructeur.

[[Prototype]] est utilisé pour la recherche des propriétés (comme le parent dans la hiérarchie classique), à ​​chaque fois qu'une propriété ne peut être trouvée dans un objet, son [[Prototype]] est recherché à la place.Un scénario d'utilisation: dites que vous souhaitez ajouter une propriété à tous les objets, vous pouvez simplement l'ajouter à Object.prototype qui s'appliquerait automatiquement à tous les objets puisque tous les objets ont Object.prototype comme racine de chaîne [[Prototype]]. Revenons à la propriété "prototype" des objets de fonction. Ce n'est utile que lorsqu'il est utilisé avec l'opérateur new. Prenez l'extrait de code suivant comme exemple:

function F() {} // function declaration 
// F now has a property named "prototype" 

var f = new F(); // use "new" operator to create a new function object based on F 

Qu'est-ce que new F() ci-dessus est d'abord créer un nouvel objet de fonctions, définissez le [[Prototype]] (lien caché) de cet objet fonction nouvellement créé pour être F.prototype, puis retourner la nouvel objet de fonction. C'est probablement ce que vous comprenez déjà qui fonctionne pour les objets de fonction. Rappelez-vous que j'ai dit que nous ne pouvons pas changer les objets de [[Prototype]]? Eh bien, au moins pas directement. La fonction Object.create de Crockford ne fait que cela, en utilisant le fait que l'opérateur new pourrait aider à définir [[Prototype]] pour nous. Ainsi, en utilisant Object.create, vous indiquez délibérément où le lien caché de votre nouvel objet doit pointer. (un peu comme indiquer qui est votre classe parent)

Dans votre exemple, conf est un objet littéral et conf.prototype n'est pas vraiment utile. Voici une autre version utilisant un style classique:

function ConfBase() {} 
ConfBase.prototype.d = 16; 
var conf = new ConfBase(); 
conf.a = 2; 
conf.b = 4; 

document.writeln(conf.a); 
document.writeln(conf.b); 
document.writeln(conf.d); 

par rapport à la réponse de @CMS, je préfère utiliser Object.create. Mais essentiellement les 2 styles utilisent le même mécanisme sous-jacent, juste que Object.create aide à le ranger.

Questions connexes