Comment créer une variable privée accessible à la fonction Prototype?

J'essaie d'avoir une prise en charge plus profonde de l'héritage prototypique et de la création de classe (je sais, il y a d'autres façons, mais dans le but, j'essaie de saisir des prototypes.) Ma question est la suivante: en utilisant l'exemple de code suivant, Y a-t-il un moyen de créer des variables privées à l'intérieur d' Tree et de Fruit qui ne seront pas retournées avec la fonction, mais sont toujours accessibles aux genus fonctions prototypes et en bulk ?

 var Tree = function ( name, size ) { this.name = name; this.size = size; }; Tree.prototype.genus = function(){ return ((typeof this.name !== 'undefined') ? this.name : 'Hybridicus Maximus'); }; Tree.prototype.bulk = function(){ return ((typeof this.size !== 'undefined') ? this.size : '8') + ' ft'; }; var Fruit = function( name, size ) { this.name = name; this.size = size; }; Fruit.prototype = new Tree(); // Fruit.prototype = Tree.prototype; -- I know this can be used, too. Fruit.prototype.bulk = function(){ return ((typeof this.size !== 'undefined') ? Math.floor(this.size / 2) : '4') + ' lbs'; }; var pine = new Tree('Pine', 9); var apple = new Fruit('Apple', 6); console.log(pine.genus(), pine.bulk()); // Outputs: "Pine 9 ft" console.log(apple.genus(), apple.bulk()); // Outputs: "Apple 3 lbs" 

EDIT : J'essaie de remplacer this.name et this.size avec des variables privées auxquelles on peut accéder dans les fonctions prototypes. Désolé pour le manque de clarté!

Oui. Tu peux le faire:

 (function() { var private = "hi"; Tree.prototype.genus = function(){ return ((typeof this.name !== 'undefined') ? this.name : 'Hybridicus Maximus'); }; Tree.prototype.bulk = function(){ return ((typeof this.size !== 'undefined') ? this.size : '8') + ' ft'; }; })(); 

Maintenant, cela fournira une variable privée que ces fonctions peuvent voir, mais ce sera une variable privée de "classe" – toutes les instances partageront la même variable, en d'autres termes. Si vous voulez une variable privée par instance, vous devez le faire dans le constructeur (ou la méthode "init", ou quoi que ce soit), ce qui signifie que les méthodes qui partagent ces personnes privées devraient également être créées là-bas. (Vous pouvez bien sûr mettre une fonction sur le prototype qui créerait les méthodes d'instance au moment de la construction.)

Edit – Une chose que vous pouvez faire est d'utiliser une technique comme celle-ci pour construire un mécanisme comme «.data ()» de jQuery, de sorte que vous disposiez d'une variable de classe qui sert d'endroit pour conserver les valeurs par instance. Il serait plutôt maladroit, mais cela pourrait être réalisable.

C'est ce que j'ai écrit dans une publication sur les cours, les membres privés et l'héritage prototypique en JavaScript . Fondamentalement, vous souhaitez créer une fonction d'accesseur de variable privée unique à chaque objet et que ces méthodes prototypes appellent cette fonction d'accesseur privé, en lui fournissant la clé qui n'est disponible que dans la fermeture:

 (function(_) { Tree = function ( name, size ) { var hidden = { name: name, size: size }; this._ = function($) { return _ === $ && hidden; }; }; Tree.prototype.genus = function(){ return ((typeof this._(_).name !== 'undefined') ? this._(_).name : 'Hybridicus Maximus'); }; Tree.prototype.bulk = function(){ return ((typeof this._(_).size !== 'undefined') ? this._(_).size : '8') + ' ft'; }; Fruit = function( name, size ) { Tree.apply(this, arguments); }; Fruit.prototype = new Tree(); // Fruit.prototype = Tree.prototype; -- I know this can be used, too. Fruit.prototype.bulk = function(){ return ((typeof this._(_).size !== 'undefined') ? Math.floor(this._(_).size / 2) : '4') + ' lbs'; }; })({}); var pine = new Tree('Pine', 9); var apple = new Fruit('Apple', 6); console.log(pine.genus(), pine.bulk()); // Outputs: "Pine 9 ft" console.log(apple.genus(), apple.bulk()); // Outputs: "Apple 3 lbs" console.log(pine._(), pine._({})); // Outputs: "false false" because outside of closure 

Vous remarquerez que la dernière ligne montre que les variables privées ne sont pas accessibles en dehors de la fermeture et ne peuvent donc être récupérées par un code tiers, à moins qu'elles ne soient disponibles par une fonction d'accesseur.

Il peut être facilement réalisé comme celui-ci

 function SharedPrivate(){ var private = "secret"; this.constructor.prototype.getP = function(){return private} this.constructor.prototype.setP = function(v){ private = v;} } var o1 = new SharedPrivate(); var o2 = new SharedPrivate(); console.log(o1.getP()); // secret console.log(o2.getP()); // secret o1.setP("Pentax Full Frame K1 is on sale..!"); console.log(o1.getP()); // Pentax Full Frame K1 is on sale..! console.log(o2.getP()); // Pentax Full Frame K1 is on sale..! o2.setP("And it's only for $1,795._"); console.log(o1.getP()); // And it's only for $1,795._ 

De toute évidence, le point clé est de créer une voie d'accès à une variable privée en utilisant une fermeture et en partageant ce point d'accès parmi les objets à créer. L'utilisation du point d'accès en tant que prototype des objets à créer pour le partage naturel est le cas idéal. En conséquence, la même fonctionnalité peut être obtenue en utilisant le modèle d'usine et Object.create() comme suit;

 function SharedPrivate(){ var priv = "secret"; return {gp : function(){return priv}, sp : function(v){priv = v} } } sharedProto = SharedPrivate(); // priv is now under closure to be shared var p1 = Object.create(sharedProto); // sharedProto becomes o1.__proto__ var p2 = Object.create(sharedProto); // sharedProto becomes o2.__proto__ 

La structure prototypique JavaScript est dorée …!