Rectangle 27 0

oop JavaScript private methods?


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

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

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

exports.MyObject = MyObject;
var MyObject = (function () {

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

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

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

    return MyObject;

})();


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

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

If you are using node.js, you don't need the IIFE part because you can take advantage of the module loading system:

JavaScript uses prototypes and don't have classes (and methods) like many object oriented languages. A JavaScript developer need to think in JavaScript.

The call function allow us to call the private function with the appropriate context (this).

This is the best answer. The benefits of private methods, no junk.

Unlike many object-oriented languages, there is no distinction between a function definition and a method definition. Rather, the distinction occurs during function calling; when a function is called as a method of an object, the function's local this keyword is bound to that object for that invocation.

Note
Rectangle 27 0

oop JavaScript private methods?


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

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

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

exports.MyObject = MyObject;
var MyObject = (function () {

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

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

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

    return MyObject;

})();


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

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

If you are using node.js, you don't need the IIFE part because you can take advantage of the module loading system:

JavaScript uses prototypes and don't have classes (and methods) like many object oriented languages. A JavaScript developer need to think in JavaScript.

The call function allow us to call the private function with the appropriate context (this).

This is the best answer. The benefits of private methods, no junk.

Unlike many object-oriented languages, there is no distinction between a function definition and a method definition. Rather, the distinction occurs during function calling; when a function is called as a method of an object, the function's local this keyword is bound to that object for that invocation.

Note
Rectangle 27 0

oop JavaScript private methods?


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

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

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

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

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

exports.MyObject = MyObject;
import MyObject from './MyObject';

let myObject = new MyObject('bar');
myObject.publicFun();      // Returns '>>bar'
myObject.privateFun('>>'); // TypeError: myObject.privateFun is not a function
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
var MyObject = require('./MyObject').MyObject;

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

@YvesM. The point of the question is choosing the best pattern that simulates it.

@janje ? What's the problem with .call ? btw you can move from ES5 and use the :: bind operator (think about using babel)

@janje Huh? That's the point of the question, there is no private f() in javascript (not at the moment).

If you are using node.js, you don't need the IIFE because you can take advantage of the module loading system:

JavaScript uses prototypes and does't have classes (or methods for that matter) like Object Oriented languages. A JavaScript developer need to think in JavaScript.

The call function allows us to call the private function with the appropriate context (this).

This is the best answer. The benefits of private methods, no junk.

Unlike many object-oriented languages, there is no distinction between a function definition and a method definition. Rather, the distinction occurs during function calling; when a function is called as a method of an object, the function's local this keyword is bound to that object for that invocation.

Note
Rectangle 27 0

oop JavaScript private methods?


Note
Rectangle 27 0

oop JavaScript private methods?


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();
    }
}

@mikesamuel - true, but only when those interpreters have bugs in them :)

Hiding thins inside the closure will not guarantee privacy on all interpreters. See code.google.com/p/google-caja/wiki/

If you make an object McDonalds() inherit from Restaurant() McDonalds can't override private methods if you declare them in this way. Well, actually you can, but it will not work if some other method calls the private, it will call the original version of the method and you also can't call the parent method. So far I have not found a good way to declare private methods that work well with inheritance. This and the performance implications makes this not a very good design pattern at all. I would recommend doing some kind of prefix to indicate private methods, likestarting with an underline.

This is a private method all right, but will tend to use up a lot more memory than an usual prototype method, especially if you are creating a lot of these objects. For every object instance, it creates a separate function bound to the object and not the class. Also, this does not get garbage collected until the object itself is destroyed.

You can do it, but the downside is that it can't be part of the prototype:

Note
Rectangle 27 0

oop JavaScript private methods?


var abdennour=new Person('Abdennour');
  abdennour.profilePublic();
(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,{});
window
Note
Rectangle 27 0

oop JavaScript private methods?


All of this closure will cost you. Make sure you test the speed implications especially in IE. You will find you are better off with a naming convention. There are still a lot of corporate web users out there that are forced to use IE6...

That 9% that are still using IE6 don't care about speed, optimizations and all modern HTML5 features. So closures won't cost anything.

about 9% of the world

Note
Rectangle 27 0

oop JavaScript private methods?


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();

He mentioned that link in the question.

I would also suggest Douglas Crockford's site as a resource on private / public methods and members javascript.crockford.com/private.html

The downside to this method is that you couldn't have private_stuff() access other private data in Restaurant and other Restaurant methods can't call private_stuff(). The upside is that if you don't need either of the conditions I just mentioned, you can keep use_restroom() in the prototype.

This should be the solution and accepted answer because the author is clearly using the prototype property.

With the pattern proposed by @georgebrock, all private data will be shared among all restaurant objects. That is akin to static private variables and functions in class based OOP. I assume that the OP does not want this. To illustrate what I mean, I created a jsFiddle.

You can simulate private methods like this:

Note
Rectangle 27 0

oop JavaScript private methods?


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

}

Also, every instance will have a full copy of the private functions, inefficient. That on top of the fact that public methods can't access private class vars, makes me want to switch to dart. Unfortunately angulardart is super beta.

Here is the class which I created to understand what Douglas Crockford's has suggested in his site Private Members in JavaScript

The that=this is a pattern that is quite common, popularized by aforementioned Crockford in his book "Javascript: The good parts"

Where is the "constructor" method in this? Where would I put logic that would normally be executed in the constructor method of a class when it is instantiated?

that is used instead of this to avoid scoping issues, when functions are bound to a different object. Here, you are storing this in that and never using it again which is the same as not doing it at all. You should change this with that all across the Constructor inner functions (not methods declaration). If employee is applyed or called in some way these methods might throw since this will be incorrectly bound.

Note
Rectangle 27 0

oop JavaScript private methods?


eval("Foo = " + Foo.toString().replace(
    /{/, "{ this.eval = function(code) { return eval(code); }; "
));
f = new Foo(99);
f.eval("x");
f.eval("y");
f.eval("x = 8");
function Foo(x) {
    var y = 5;
    var bar = function() {
        return y * x;
    };

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

@James None that I know of, I think it's the nature of the beast. As I pointed out you can move functionality to the server where it runs in a protected environment. The point I wanted to get over in my answer though is that Crockford's solution is not helping, unnecessarily complicates code and hides the necessity to do something about it.

@James This is getting OT, if you want to continue this please open a new question. Yes, an attacker can read the password. From your "private" variable. Or from the DOM. Or he can replace the AJAX API. Or he replaces your page with something else. If he can't do any of the above then there is no need for JS "privacy" because he can't read any of your JS variables either. The point is that Crockford's "solution" that everyone is using right now is not helping with this problem.

After this is executed any object created with new Foo() is going to have an eval method which can be called to return or change values or methods defined in the constructor's closure, e.g.:

I do usually use leading underscores to mark __private and _protected methods and fields (Perl style), but the idea of having privacy in JavaScript just shows how it's a misunderstood language.

If a user entersa secret password, he can't do this server-side. At some point the password will be in a 'private' var. So could an attacker read it? I trust my code, and anyway my house standards do not permit eval(). The attacker could be some malicious third party JavaScript plug-in or library that I didn't check properly - so, yes I need to check these. The attacker might also be something like an advert on the side that should not interact with my code. I protect against that by wrapping all my code in an anonymous (function () {allMyStuff}()); so as to expose nothing global.

In any case where the attacker has no "execute" right on the JS context he has no way of accessing any "public" or "private" fields or methods. In case the attacker does have that access he can execute this one-liner:

In my opinion, this pretty much makes Crockford's solution useless. Since the "privacy" is easily broken the downsides of his solution (reduced readability & maintainability, decreased performance, increased memory) makes the "no privacy" prototype based method the better choice.

Note that the above code is generic to all constructor-type-privacy. It will fail with some of the solutions here but it should be clear that pretty much all of the closure based solutions can be broken like this with different replace() parameters.

So how do you get real privacy in JS? Put everything that is required to be private on the server side and use JS to do AJAX calls.

Take any of the solutions that follow Crockford's private or priviledged pattern. For example:

The only problem I can see with this that it won't work for cases where there is only one instance and it's created on load. But then there is no reason to actually define a prototype and in that case the attacker can simply recreate the object instead of the constructor as long as he has a way of passing the same parameters (e.g. they are constant or calculated from available values).

This is a serious issue which should be more well known. Is there a 'defence' against this attack?

Note