Méthodes privées JavaScript


Answers

Vous pouvez le faire, mais l'inconvénient est qu'il ne peut pas faire partie du prototype:

function Restaurant()
{
    var myPrivateVar;

    var private_stuff = function()   // Only visible inside Restaurant()
    {
        myPrivateVar = "I can set this here!";
    }

    this.use_restroom = function()   // use_restroom is visible to all
    {
        private_stuff();
    }

    this.buy_food = function()    // buy_food is visible to all
    {
        private_stuff();
    }
}
Question

Pour créer une classe JavaScript avec une méthode publique, je ferais quelque chose comme:

function Restaurant() {}

Restaurant.prototype.buy_food = function(){
   // something here
}

Restaurant.prototype.use_restroom = function(){
   // something here
}

De cette façon, les utilisateurs de ma classe peuvent:

var restaurant = new Restaurant();
restaurant.buy_food();
restaurant.use_restroom();

Comment créer une méthode privée qui peut être appelée par les méthodes buy_food et use_restroom mais pas par les utilisateurs de la classe?

En d'autres termes, je souhaite que l'implémentation de ma méthode soit capable de faire:

Restaurant.prototype.use_restroom = function() {
   this.private_stuff();
}

Mais cela ne devrait pas fonctionner:

var r = new Restaurant();
r.private_stuff();

Comment puis-je définir private_stuff comme une méthode privée, donc les deux sont vraies?

J'ai lu l'écriture de Doug Crockford à quelques reprises, mais il ne semble pas que les méthodes «privées» puissent être appelées par des méthodes publiques et que les méthodes «privilégiées» puissent être appelées de l'extérieur.




Voir cette réponse pour une solution «classe» propre et simple avec une interface privée et publique et un support pour la composition




Je préfère stocker des données privées dans un associé WeakMap. Cela vous permet de garder vos méthodes publiques sur le prototype où ils appartiennent. Cela semble être le moyen le plus efficace de gérer ce problème pour un grand nombre d'objets.

const data = new WeakMap();

function Foo(value) {
    data.set(this, {value});
}

// public method accessing private value
Foo.prototype.accessValue = function() {
    return data.get(this).value;
}

// private 'method' accessing private value
function accessValue(foo) {
    return data.get(foo).value;
}

export {Foo};



Voici la classe que j'ai créée pour comprendre ce que Douglas Crockford a suggéré sur son site Membres Privés en JavaScript

function Employee(id, name) { //Constructor
    //Public member variables
    this.id = id;
    this.name = name;
    //Private member variables
    var fName;
    var lName;
    var that = this;
    //By convention, we create a private variable 'that'. This is used to     
    //make the object available to the private methods. 

    //Private function
    function setFName(pfname) {
        fName = pfname;
        alert('setFName called');
    }
    //Privileged function
    this.setLName = function (plName, pfname) {
        lName = plName;  //Has access to private variables
        setFName(pfname); //Has access to private function
        alert('setLName called ' + this.id); //Has access to member variables
    }
    //Another privileged member has access to both member variables and private variables
    //Note access of this.dataOfBirth created by public member setDateOfBirth
    this.toString = function () {
        return 'toString called ' + this.id + ' ' + this.name + ' ' + fName + ' ' + lName + ' ' + this.dataOfBirth; 
    }
}
//Public function has access to member variable and can create on too but does not have access to private variable
Employee.prototype.setDateOfBirth = function (dob) {
    alert('setDateOfBirth called ' + this.id);
    this.dataOfBirth = dob;   //Creates new public member note this is accessed by toString
    //alert(fName); //Does not have access to private member
}
$(document).ready()
{
    var employee = new Employee(5, 'Shyam'); //Create a new object and initialize it with constructor
    employee.setLName('Bhaskar', 'Ram');  //Call privileged function
    employee.setDateOfBirth('1/1/2000');  //Call public function
    employee.id = 9;                     //Set up member value
    //employee.setFName('Ram');  //can not call Private Privileged method
    alert(employee.toString());  //See the changed object

}



Les fonctions privées ne peuvent pas accéder aux variables publiques en utilisant le modèle de module




J'ai évoqué ceci: EDIT: En fait, quelqu'un a lié à une solution identique. Duh!

var Car = function() {
}

Car.prototype = (function() {
    var hotWire = function() {
        // Private code *with* access to public properties through 'this'
        alert( this.drive() ); // Alerts 'Vroom!'
    }

    return {
        steal: function() {
            hotWire.call( this ); // Call a private method
        },
        drive: function() {
            return 'Vroom!';
        }
    };
})();

var getAwayVechile = new Car();

hotWire(); // Not allowed
getAwayVechile.hotWire(); // Not allowed
getAwayVechile.steal(); // Alerts 'Vroom!'



I know it's a bit too late but how about this?

var obj = function(){
    var pr = "private";
    var prt = Object.getPrototypeOf(this);
    if(!prt.hasOwnProperty("showPrivate")){
        prt.showPrivate = function(){
            console.log(pr);
        }
    }    
}

var i = new obj();
i.showPrivate();
console.log(i.hasOwnProperty("pr"));



Dans ces situations, lorsque vous avez une API publique et que vous souhaitez utiliser des méthodes / propriétés privées et publiques, j'utilise toujours le modèle de module. Ce modèle a été rendu populaire dans la bibliothèque YUI, et les détails peuvent être trouvés ici:

http://yuiblog.com/blog/2007/06/12/module-pattern/

C'est vraiment simple, et facile à comprendre pour les autres développeurs. Pour un exemple simple:

var MYLIB = function() {  
    var aPrivateProperty = true;
    var aPrivateMethod = function() {
        // some code here...
    };
    return {
        aPublicMethod : function() {
            aPrivateMethod(); // okay
            // some code here...
        },
        aPublicProperty : true
    };  
}();

MYLIB.aPrivateMethod() // not okay
MYLIB.aPublicMethod() // okay






Puisque tout le monde postait ici son propre code, je vais le faire aussi ...

J'aime Crockford parce qu'il a introduit de vrais modèles orientés objet en Javascript. Mais il est également venu avec un nouveau malentendu, le "ça".

Alors pourquoi utilise-t-il "that = this"? Cela n'a rien à voir avec des fonctions privées. Cela a à voir avec les fonctions internes!

Parce que, selon Crockford, c'est un code buggé:

Function Foo( ) {
    this.bar = 0; 
    var foobar=function( ) {
        alert(this.bar);
    }
} 

Alors il a suggéré de faire ceci:

Function Foo( ) {
    this.bar = 0;
    that = this; 
    var foobar=function( ) {
        alert(that.bar);
    }
}

Donc, comme je l'ai dit, je suis tout à fait sûr que Crockford a eu tort d'expliquer cela et cela (mais son code est certainement correct). Ou était-il juste en train de tromper le monde Javascript, pour savoir qui copie son code? Je ne sais pas ... je ne suis pas un navigateur geek; D

MODIFIER

Ah, c'est tout ce qui compte: Qu'est-ce que 'var that = this'? signifie en JavaScript?

Donc, Crockie avait vraiment tort avec son explication ... mais juste avec son code, donc il est toujours un bon gars. :))




Toute cette fermeture vous coûtera. Assurez-vous de tester les implications de vitesse en particulier dans IE. Vous trouverez que vous êtes mieux avec une convention de nommage. Il y a encore beaucoup d'internautes qui sont obligés d'utiliser IE6 ...




There are many answers on this question already, but nothing fitted my needs. So i came up with my own solution, I hope it is usefull for someone:

function calledPrivate(){
    var stack = new Error().stack.toString().split("\n");
    function getClass(line){
        var i = line.indexOf(" ");
        var i2 = line.indexOf(".");
        return line.substring(i,i2);
    }
    return getClass(stack[2])==getClass(stack[3]);
}

class Obj{
    privateMethode(){
        if(calledPrivate()){
            console.log("your code goes here");
        }
    }
    publicMethode(){
        this.privateMethode();
    }
}

var obj = new Obj();
obj.publicMethode(); //logs "your code goes here"
obj.privateMethode(); //does nothing

As you can see this system works when using this type of classes in javascript. As far as I figured out none of the methods commented above did.




Prenez l'une des solutions qui suivent le modèle privé ou privilégié de Crockford. Par exemple:

function Foo(x) {
    var y = 5;
    var bar = function() {
        return y * x;
    };

    this.public = function(z) {
        return bar() + x * z;
    };
}

Dans tous les cas où l'attaquant n'a pas de droit "execute" sur le contexte JS, il n'a aucun moyen d'accéder aux champs ou méthodes "publics" ou "privés". Dans le cas où l'attaquant a cet accès, il peut exécuter ce one-liner:

eval("Foo = " + Foo.toString().replace(
    /{/, "{ this.eval = function(code) { return eval(code); }; "
));

Notez que le code ci-dessus est générique pour tout constructeur-type-privacy. Il échouera avec certaines des solutions ici, mais il devrait être clair que pratiquement toutes les solutions basées sur la fermeture peuvent être brisées comme cela avec différents paramètres replace() .

Après cela, tout objet créé avec un new Foo() va avoir une méthode eval qui peut être appelée pour retourner ou modifier des valeurs ou des méthodes définies dans la fermeture du constructeur, par exemple:

f = new Foo(99);
f.eval("x");
f.eval("y");
f.eval("x = 8");

Le seul problème que je peux voir avec cela que cela ne fonctionnera pas dans les cas où il n'y a qu'une seule instance et il est créé sur le chargement. Mais alors il n'y a pas de raison de définir réellement un prototype et dans ce cas l'attaquant peut simplement recréer l'objet au lieu du constructeur tant qu'il a le moyen de transmettre les mêmes paramètres (par exemple constants ou calculés à partir des valeurs disponibles).

À mon avis, cela rend la solution de Crockford pratiquement inutile. Puisque la «vie privée» est facilement brisée, les inconvénients de sa solution (lisibilité et maintenabilité réduites, diminution des performances, augmentation de la mémoire) font de la méthode «sans confidentialité» basée sur un prototype le meilleur choix.

J'utilise généralement des caractères de soulignement pour marquer les méthodes et champs __private et _protected (style Perl), mais l'idée d'avoir de la confidentialité dans JavaScript montre simplement que c'est un langage mal compris.

Par conséquent, je ne suis pas d'accord avec Crockford sauf pour sa première phrase.

Alors, comment obtenez-vous la vraie vie privée dans JS? Mettez tout ce qui doit être privé côté serveur et utilisez JS pour faire des appels AJAX.




En général, j'ai ajouté l'objet privé _ temporairement à l'objet. Vous devez ouvrir la confidentialité exlipcitly dans le "Power-constructeur" pour la méthode. Si vous appelez la méthode à partir du prototype, vous serez en mesure d'écraser la méthode prototype

  • Rendre une méthode publique accessible dans le "Power-constructeur": (ctx est le contexte de l'objet)

    ctx.test = GD.Fabric.open('test', GD.Test.prototype, ctx, _); // is a private object
    
  • Maintenant j'ai cette openPrivacy:

    GD.Fabric.openPrivacy = function(func, clss, ctx, _) {
        return function() {
            ctx._ = _;
            var res = clss[func].apply(ctx, arguments);
            ctx._ = null;
            return res;
        };
    };
    



Envelopper tout le code dans la fonction anonyme: Ensuite, toutes les fonctions seront privées, seules les fonctions attachées à l'objet window :

(function(w,nameSpacePrivate){
     w.Person=function(name){
         this.name=name;   
         return this;
     };

     w.Person.prototype.profilePublic=function(){
          return nameSpacePrivate.profile.call(this);
     };  

     nameSpacePrivate.profile=function(){
       return 'My name is '+this.name;
     };

})(window,{});

Utilisez ceci :

  var abdennour=new Person('Abdennour');
  abdennour.profilePublic();

FIDDLE




I have created a new tool to allow you to have true private methods on the prototype https://github.com/TremayneChrist/ProtectJS

Exemple:

var MyObject = (function () {

  // Create the object
  function MyObject() {}

  // Add methods to the prototype
  MyObject.prototype = {

    // This is our public method
    public: function () {
      console.log('PUBLIC method has been called');
    },

    // This is our private method, using (_)
    _private: function () {
      console.log('PRIVATE method has been called');
    }
  }

  return protect(MyObject);

})();

// Create an instance of the object
var mo = new MyObject();

// Call its methods
mo.public(); // Pass
mo._private(); // Fail



You have to put a closure around your actual constructor-function, where you can define your private methods. To change data of the instances through these private methods, you have to give them "this" with them, either as an function argument or by calling this function with .apply(this) :

var Restaurant = (function(){
    var private_buy_food = function(that){
        that.data.soldFood = true;
    }
    var private_take_a_shit = function(){
        this.data.isdirty = true;   
    }
    // New Closure
    function restaurant()
    {
        this.data = {
            isdirty : false,
            soldFood: false,
        };
    }

    restaurant.prototype.buy_food = function()
    {
       private_buy_food(this);
    }
    restaurant.prototype.use_restroom = function()
    {
       private_take_a_shit.call(this);
    }
    return restaurant;
})()

// TEST:

var McDonalds = new Restaurant();
McDonalds.buy_food();
McDonalds.use_restroom();
console.log(McDonalds);
console.log(McDonalds.__proto__);



Et ça?

var Restaurant = (function() {

 var _id = 0;
 var privateVars = [];

 function Restaurant(name) {
     this.id = ++_id;
     this.name = name;
     privateVars[this.id] = {
         cooked: []
     };
 }

 Restaurant.prototype.cook = function (food) {
     privateVars[this.id].cooked.push(food);
 }

 return Restaurant;

})();

La recherche de variable privée est impossible en dehors de la portée de la fonction immédiate. Il n'y a pas de duplication de fonctions, ce qui permet d'économiser de la mémoire.

L'inconvénient est que la recherche de variables privées est clunky privateVars[this.id].cooked est ridicule à taper. Il y a aussi une variable "id" supplémentaire.




Le modèle de module est correct dans la plupart des cas. Mais si vous avez des milliers d'instances, les classes sauvegardent la mémoire. Si l'enregistrement de la mémoire est une préoccupation et que vos objets contiennent une petite quantité de données privées, mais ont beaucoup de fonctions publiques, alors vous voudrez que toutes les fonctions publiques vivent dans le .prototype pour économiser de la mémoire.

C'est ce que j'ai trouvé:

var MyClass = (function () {
    var secret = {}; // You can only getPriv() if you know this
    function MyClass() {
        var that = this, priv = {
            foo: 0 // ... and other private values
        };
        that.getPriv = function (proof) {
            return (proof === secret) && priv;
        };
    }
    MyClass.prototype.inc = function () {
        var priv = this.getPriv(secret);
        priv.foo += 1;
        return priv.foo;
    };
    return MyClass;
}());
var x = new MyClass();
x.inc(); // 1
x.inc(); // 2

L'objet priv contient des propriétés privées. Il est accessible via la fonction publique getPriv() , mais cette fonction renvoie false moins que vous ne lui transmettiez le secret , et ceci n'est connu que dans la fermeture principale.




var TestClass = function( ) {

    var privateProperty = 42;

    function privateMethod( ) {
        alert( "privateMethod, " + privateProperty );
    }

    this.public = {
        constructor: TestClass,

        publicProperty: 88,
        publicMethod: function( ) {
            alert( "publicMethod" );
            privateMethod( );
        }
    };
};
TestClass.prototype = new TestClass( ).public;


var myTestClass = new TestClass( );

alert( myTestClass.publicProperty );
myTestClass.publicMethod( );

alert( myTestClass.privateMethod || "no privateMethod" );

Semblable à georgebrock, mais un peu moins verbeux (IMHO) Des problèmes à le faire de cette façon? (Je ne l'ai jamais vu nulle part)

edit: J'ai réalisé que c'est un peu inutile car chaque instanciation indépendante possède sa propre copie des méthodes publiques, ce qui sape l'utilisation du prototype.




Utilisation de la fonction et de l'appel auto-invoquant

JavaScript utilise des prototypes et n'a pas de classes (ou de méthodes d'ailleurs) comme les langages orientés objet. Un développeur JavaScript doit penser en JavaScript.

Citation de Wikipedia:

Contrairement à de nombreux langages orientés objet, il n'y a pas de distinction entre une définition de fonction et une définition de méthode. Au contraire, la distinction se produit pendant l'appel de fonction; Lorsqu'une fonction est appelée en tant que méthode d'un objet, le mot clé local de la fonction est lié à cet objet pour cet appel.

Solution utilisant une fonction auto-invoquante et la fonction call pour appeler la "méthode" privée:

var MyObject = (function () {

    // Constructor
    function MyObject (foo) {
        this._foo = foo;
    }

    function privateFun (prefix) {
        return prefix + this._foo;
    }

    MyObject.prototype.publicFun = function () {
        return privateFun.call(this, '>>');
    }

    return MyObject;
})();


var myObject = new MyObject('bar');
myObject.publicFun();      // Returns '>>bar'
myObject.privateFun('>>'); // ReferenceError: private is not defined

La fonction call nous permet d'appeler la fonction privée avec le contexte approprié ( this ).


Simpler avec Node.js

Si vous utilisez node.js , vous n'avez pas besoin de l' IIFE, car vous pouvez tirer parti du système de chargement du module :

function MyObject (foo) {
    this._foo = foo;
}

function privateFun (prefix) {
    return prefix + this._foo;
}

MyObject.prototype.publicFun = function () {
    return privateFun.call(this, '>>');
}

exports.MyObject = MyObject;

Chargez le fichier:

var MyObject = require('./MyObject').MyObject;

var myObject = new MyObject('bar');
myObject.publicFun();      // Returns '>>bar'
myObject.privateFun('>>'); // ReferenceError: private is not defined


ES7 (expérimental) avec l'opérateur Bind

L'opérateur bind :: est une proposal ECMAScript et est implémenté dans Babel ( étape 0 ).

export default class MyObject {
  constructor (foo) {
    this._foo = foo;
  }

  publicFun () {
    return this::privateFun('>>');
  }
}

function privateFun (prefix) {
  return prefix + this._foo;
}

Chargez le fichier:

import MyObject from './MyObject';

let myObject = new MyObject('bar');
myObject.publicFun();      // Returns '>>bar'
myObject.privateFun('>>'); // TypeError: myObject.privateFun is not a function



C'est ce que j'ai travaillé:

A besoin d'une classe de code de sucre que vous pouvez trouver ici . Prend également en charge les éléments protégés, hérités, virtuels, statiques ...

;( function class_Restaurant( namespace )
{
    'use strict';

    if( namespace[ "Restaurant" ] ) return    // protect against double inclusions

        namespace.Restaurant = Restaurant
    var Static               = TidBits.OoJs.setupClass( namespace, "Restaurant" )


    // constructor
    //
    function Restaurant()
    {
        this.toilets = 3

        this.Private( private_stuff )

        return this.Public( buy_food, use_restroom )
    }

    function private_stuff(){ console.log( "There are", this.toilets, "toilets available") }

    function buy_food     (){ return "food"        }
    function use_restroom (){ this.private_stuff() }

})( window )


var chinese = new Restaurant

console.log( chinese.buy_food()      );  // output: food
console.log( chinese.use_restroom()  );  // output: There are 3 toilets available
console.log( chinese.toilets         );  // output: undefined
console.log( chinese.private_stuff() );  // output: undefined

// and throws: TypeError: Object #<Restaurant> has no method 'private_stuff'



Class({  
    Namespace:ABC,  
    Name:"ClassL2",  
    Bases:[ABC.ClassTop],  
    Private:{  
        m_var:2  
    },  
    Protected:{  
        proval:2,  
        fight:Property(function(){  
            this.m_var--;  
            console.log("ClassL2::fight (m_var)" +this.m_var);  
        },[Property.Type.Virtual])  
    },  
    Public:{  
        Fight:function(){  
            console.log("ClassL2::Fight (m_var)"+this.m_var);  
            this.fight();  
        }  
    }  
});  

https://github.com/nooning/JSClass




Je pense que de telles questions reviennent encore et encore à cause du manque de compréhension des fermetures. Сlosures est la chose la plus importante dans JS. Chaque programmeur JS doit en ressentir l'essence.

1. Tout d'abord, nous devons faire une portée séparée (fermeture).

function () {

}

2. Dans ce domaine, nous pouvons faire ce que nous voulons. Et personne ne le saura.

function () {
    var name,
        secretSkills = {
            pizza: function () { return new Pizza() },
            sushi: function () { return new Sushi() }
        }

    function Restaurant(_name) {
        name = _name
    }
    Restaurant.prototype.getFood = function (name) {
        return name in secretSkills ? secretSkills[name]() : null
    }
}

3. Pour que le monde connaisse notre classe de restaurant, nous devons le retourner de la fermeture.

var Restaurant = (function () {
    // Restaurant definition
    return Restaurant
})()

4. À la fin, nous avons:

var Restaurant = (function () {
    var name,
        secretSkills = {
            pizza: function () { return new Pizza() },
            sushi: function () { return new Sushi() }
        }

    function Restaurant(_name) {
        name = _name
    }
    Restaurant.prototype.getFood = function (name) {
        return name in secretSkills ? secretSkills[name]() : null
    }
    return Restaurant
})()

5. En outre, cette approche a un potentiel d'héritage et de templating

// Abstract class
function AbstractRestaurant(skills) {
    var name
    function Restaurant(_name) {
        name = _name
    }
    Restaurant.prototype.getFood = function (name) {
        return skills && name in skills ? skills[name]() : null
    }
    return Restaurant
}

// Concrete classes
SushiRestaurant = AbstractRestaurant({ 
    sushi: function() { return new Sushi() } 
})

PizzaRestaurant = AbstractRestaurant({ 
    pizza: function() { return new Pizza() } 
})

var r1 = new SushiRestaurant('Yo! Sushi'),
    r2 = new PizzaRestaurant('Dominos Pizza')

r1.getFood('sushi')
r2.getFood('pizza')

J'espère que cela aide quelqu'un à mieux comprendre ce sujet




Here's what i enjoyed the most so far regarding private/public methods/members and instantiation in javascript:

here is the article: http://www.sefol.com/?p=1090

and here is the example:

var Person = (function () {

    //Immediately returns an anonymous function which builds our modules 
    return function (name, location) {

        alert("createPerson called with " + name);

        var localPrivateVar = name;

        var localPublicVar = "A public variable";

        var localPublicFunction = function () {
            alert("PUBLIC Func called, private var is :" + localPrivateVar)
        };

        var localPrivateFunction = function () {
            alert("PRIVATE Func called ")
        };

        var setName = function (name) {

            localPrivateVar = name;

        }

        return {

            publicVar: localPublicVar,

            location: location,

            publicFunction: localPublicFunction,

            setName: setName

        }

    }
})();


//Request a Person instance - should print "createPerson called with ben"
var x = Person("ben", "germany");

//Request a Person instance - should print "createPerson called with candide"
var y = Person("candide", "belgium");

//Prints "ben"
x.publicFunction();

//Prints "candide"
y.publicFunction();

//Now call a public function which sets the value of a private variable in the x instance
x.setName("Ben 2");

//Shouldn't have changed this : prints "candide"
y.publicFunction();

//Should have changed this : prints "Ben 2"
x.publicFunction();

JSFiddle: http://jsfiddle.net/northkildonan/kopj3dt3/1/




Personnellement, je préfère le modèle suivant pour créer des classes en JavaScript:

var myClass = (function() {
    // Private class properties go here

    var blueprint = function() {
        // Private instance properties go here
        ...
    };

    blueprint.prototype = { 
        // Public class properties go here
        ...
    };

    return  {
         // Public class properties go here
        create : function() { return new blueprint(); }
        ...
    };
})();

Comme vous pouvez le voir, il vous permet de définir à la fois les propriétés de classe et les propriétés d'instance, chacune pouvant être publique et privée.

Démo

var Restaurant = function() {
    var totalfoodcount = 0;        // Private class property
    var totalrestroomcount  = 0;   // Private class property
    
    var Restaurant = function(name){
        var foodcount = 0;         // Private instance property
        var restroomcount  = 0;    // Private instance property
        
        this.name = name
        
        this.incrementFoodCount = function() {
            foodcount++;
            totalfoodcount++;
            this.printStatus();
        };
        this.incrementRestroomCount = function() {
            restroomcount++;
            totalrestroomcount++;
            this.printStatus();
        };
        this.getRestroomCount = function() {
            return restroomcount;
        },
        this.getFoodCount = function() {
            return foodcount;
        }
    };
   
    Restaurant.prototype = {
        name : '',
        buy_food : function(){
           this.incrementFoodCount();
        },
        use_restroom : function(){
           this.incrementRestroomCount();
        },
        getTotalRestroomCount : function() {
            return totalrestroomcount;
        },
        getTotalFoodCount : function() {
            return totalfoodcount;
        },
        printStatus : function() {
           document.body.innerHTML
               += '<h3>Buying food at '+this.name+'</h3>'
               + '<ul>' 
               + '<li>Restroom count at ' + this.name + ' : '+ this.getRestroomCount() + '</li>'
               + '<li>Food count at ' + this.name + ' : ' + this.getFoodCount() + '</li>'
               + '<li>Total restroom count : '+ this.getTotalRestroomCount() + '</li>'
               + '<li>Total food count : '+ this.getTotalFoodCount() + '</li>'
               + '</ul>';
        }
    };

    return  { // Singleton public properties
        create : function(name) {
            return new Restaurant(name);
        },
        printStatus : function() {
          document.body.innerHTML
              += '<hr />'
              + '<h3>Overview</h3>'
              + '<ul>' 
              + '<li>Total restroom count : '+ Restaurant.prototype.getTotalRestroomCount() + '</li>'
              + '<li>Total food count : '+ Restaurant.prototype.getTotalFoodCount() + '</li>'
              + '</ul>'
              + '<hr />';
        }
    };
}();

var Wendys = Restaurant.create("Wendy's");
var McDonalds = Restaurant.create("McDonald's");
var KFC = Restaurant.create("KFC");
var BurgerKing = Restaurant.create("Burger King");

Restaurant.printStatus();

Wendys.buy_food();
Wendys.use_restroom();
KFC.use_restroom();
KFC.use_restroom();
Wendys.use_restroom();
McDonalds.buy_food();
BurgerKing.buy_food();

Restaurant.printStatus();

BurgerKing.buy_food();
Wendys.use_restroom();
McDonalds.buy_food();
KFC.buy_food();
Wendys.buy_food();
BurgerKing.buy_food();
McDonalds.buy_food();

Restaurant.printStatus();

Voir aussi ce violon .




Vous pouvez simuler des méthodes privées comme ceci:

function Restaurant() {
}

Restaurant.prototype = (function() {
    var private_stuff = function() {
        // Private code here
    };

    return {

        constructor:Restaurant,

        use_restroom:function() {
            private_stuff();
        }

    };
})();

var r = new Restaurant();

// This will work:
r.use_restroom();

// This will cause an error:
r.private_stuff();

Plus d'informations sur cette technique ici: http://webreflection.blogspot.com/2008/04/natural-javascript-private-methods.html




Si vous voulez la gamme complète de fonctions publiques et privées avec la possibilité pour les fonctions publiques d'accéder à des fonctions privées, code de disposition pour un objet comme ceci:

function MyObject(arg1, arg2, ...) {
  //constructor code using constructor arguments...
  //create/access public variables as 
  // this.var1 = foo;

  //private variables

  var v1;
  var v2;

  //private functions
  function privateOne() {
  }

  function privateTwon() {
  }

  //public functions

  MyObject.prototype.publicOne = function () {
  };

  MyObject.prototype.publicTwo = function () {
  };
}