Comprendre les variables publiques / privées de l'instance

Je lis un tutoriel sur les méthodes public / privé et je ne peux pas comprendre la différence.

Pour une méthode privée, il dit: «Les membres privés sont fabriqués par le constructeur. Les variables et les paramètres ordinaires du constructeur deviennent les membres privés».

function Container(param) { this.member = param; var secret = 3; var that = this; } 

Et pour les méthodes publiques, "cette technique est habituellement utilisée pour initialiser les variables publiques de l'instance. La variable du constructeur est utilisée pour ajouter des membres à l'objet".

 function Container(param) { this.member = param; } 

Comme vous pouvez le voir, les deux fonctions ont un params et un this.member = param; . Pourtant, l'une est une variable d'instance privée et l'autre est une variable d'instance publique?

Comprendre les fermetures

L'ouverture d'un nouveau corps de fonction crée une nouvelle portée. Ce type de portée s'appelle une fermeture dans JS. Les variables créées dans cette zone sont accessibles dans toutes ses sous-étendues. Cela signifie que toute variable créée par var sera rendue visible pour les sous-fonctions. Dans cet exemple, myTemporaryVar est accessible dans SubScope.

 function myParentScope() { var myTemporaryVar = "sample"; function subScope() { console.log(myTemporaryVar); } return subScope(); } 

Lorsque vous utilisez une fonction avec le new mot-clé, une nouvelle fermeture est créée pour l'instance actuelle. Toute fonction créée dans ce constructeur gardera l'accès aux variables de portée. Dans l'exemple suivant, la fonction sayHi peut accéder à la variable temporaire myName.

 function Person(name) { var myName = name; this.sayHi = function() { console.log("Hi, my name is " + myName + "."); }; } p = new Person("Bob"); p.sayHi(); // Hi, my name is Bob. 

En fait, les paramètres passés sont les mêmes que les variables de la variable. Les paramètres du constructeur sont accessibles dans n'importe quelle sous-fonction. Ainsi, l'exemple précédent peut être réduit à:

 function Person(name) { this.sayHi = function() { console.log("Hi, my name is " + name + "."); }; } p = new Person("Bob"); p.sayHi(); // Hi, my name is Bob. 

Il s'agit d'une caractéristique très unique de JavaScript car cela signifie que les variables de création de variables existent encore après la fin de la fonction tant qu'il existe encore un moyen d'y accéder.

Simulation de la confidentialité de l'OOP basée sur la classe

Les fermetures peuvent être «abusées» pour créer des membres privés avec des fonctions getter et setter.

 function Person(name) { this.getName = function() { return name; }; this.setName = function(newname) { name = newname; }; } p = new Person("Bob"); console.log(p.getName()); // "Bob" p.setName("Alice"); console.log(p.getName()); // "Alice" p.name; // undefined 

Pourquoi ce n'est pas une véritable confidentialité

Le getter et le setter doivent être créés dans le constructeur afin d'accéder à la variable var . Les méthodes ajoutées dans le mode prototype-extension commun ne peuvent pas y accéder. Les méthodes de prototypes doivent également utiliser les créateurs et les getters, ce qui rend l'intimité de ces variables tout à fait inutile.

 Person.prototype.sayGoodMorning = function() { console.log("Good morning, my name is " + this.getName() + "."); } 

La seule façon d'accéder directement à la variable dans une méthode est de la créer réellement dans le constructeur. Mais mettre toutes les méthodes dans le constructeur est extrêmement inefficace car une nouvelle copie des méthodes sera créée pour chaque instance. C'est pourquoi de nombreuses personnes préfèrent simplement utiliser une notation personnalisée pour identifier d'éventuels membres privés. Le Guide de style Google JavaScript recommande de placer un trait de soulignement à la fin du nom de la variable.

 function Person(name) { this.name_ = name; } Person.prototype.getName = function() { return this.name_; } Person.prototype.setName = function(name) { this.name_ = name; } Person.prototype.sayGoodMorning = function() { console.log("Good morning, my name is " + this.name_ + "."); } 

Il incombe au programmeur de ne pas être stupide et d'accéder aux éventuels membres privés. Notez que cela va en contradiction totale avec l'opinion de Crockford, mais à chacun est propre. J'ai appris JS après Python, donc la vie privée de soulignement est comme une seconde nature pour moi.

Aucune de ces variables n'est vraiment privée car si vous instanciez Container, vous pouvez accéder à une variable secrète:

 function Container(param) { this.member = param; var secret = 3; var that = this; } var container = new Container(); console.log(container.secret); container.secret = "toto"; console.log(container.secret); console.log(container); 

Voici le résultat:

Console

Comme vous pouvez le voir, vous pouvez accéder au secret sans "Getter / Setter".

Si vous souhaitez faire javascript objet avec une variable vraiment privée, regardez ce tutoriel:

http://blog.stchur.com/2011/09/26/true-private-variables-in-javascript-with-prototype/