1

In a class-based language like Java, I sometimes take advantage of the fact that a private member of a class is accessible by other objects of the same class. For example,

class BitSet {
    private int[] words;

    public void and(BitSet set) {
        for (int i = 0; i < words.length; i++)
            words[i] &= (i < set.words.length) ? set.words[i] : 0; 
    }
}

Now, I'm working JavaScript using the constructor pattern to create "private" members:

function BitSet() {
    var words = [];

    this.and = function (set) {
        // This is roughly what I'm trying to achieve.
        for (i = 0; i < words.length; i++)
             words[i] &= (i < set.words.length) ? set.words[i] : 0;
    }

    // This would solve the problem,
    // but exposes the implementation of the object and
    // clutters up the API for the user

    this.getWord = function(index) {
        return words[index];
    }
}

I know I should probably be approaching this problem differently (and not so object-oriented). Does anyone have a suggestion for a better pattern?

Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
  • just make it a variable if you don't want it public, you can still call it anywhere in the constructor... – dandavis Oct 09 '13 at 20:57
  • 2
    javascript has no privat's, but closures, that is a different concept – philipp Oct 09 '13 at 20:57
  • @philipp javascript absolutely has private members... function Foo(){ var privateMember = 1;} var foo = new Foo(); console.log(foo.privateMember);//doesn't work cause it's private. – Yevgeny Simkin Oct 10 '13 at 08:11
  • @GeniaS. that's a closure, not a private. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures I never used the closure pattern to create privates because in my opinion is quite pointless. To protect your methods? If someone can inject script that would do that then you'd have a much bigger problem than that. To prevent consumers of your framework/library to use it? You can use the naming convention: `_mypravite` With all the downsides to it I don't see how they'd out way the upside. – HMR Oct 10 '13 at 11:43
  • Aton, some more info about prototype, inheritance, overriding and calling super: http://stackoverflow.com/a/16063711/1641941 – HMR Oct 10 '13 at 11:49

1 Answers1

1

JavaScript is a prototypal object-oriented programming language, not a classical object-oriented programming language. There are no classes in JavaScript but you can model prototypes as classes due to prototype-class isomorphism:

function CLASS(prototype) {
    var constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
}

The CLASS function allows you to create prototypes which look like classes. However they are not classes. Unlike classes in other languages prototypes in JavaScript have no access specifiers. Everything must be either public or hidden inside closures:

var BitSet = CLASS({
    constructor: function () {
        this.words = [];
    },
    and: function (set) {
        var length = this.words.length, setWords = set.words;
        for (var i = 0; i < length; i++) this.words[i] &= setWords[i] || 0;
    }
});

In fact it is a good thing that JavaScript doesn't have classes or access specifiers because you really don't need them. Think about it. Do you really need access specifiers in languages like Java either? If everything was public would it really make such a big difference? In my humble opinion it wouldn't.

Some people argue that making everything public is bad because it exposes implementation details and unnecessarily clutters the user API. Not true. Just don't document those properties which you wish to keep private. If the user doesn't need to know about a certain property then just don't document it.

If you need to make a variable private for security purposes then JavaScript has closures. Such properties shouldn't need to be accessed by other objects (even of the same class) anyway. Hence there shouldn't be a situation in which you need to keep a variable private and making it accessible to other classes of objects too.

Finally there are lots of advantages of making properties public:

  1. Since the property is public you don't need to create closures inside the constructor function.
  2. Methods can be shared on the prototype. Hence all instances of the class share methods.
  3. You can separate object initialization from the methods of the object.
  4. The code is more readable and maintainable.
  5. Object creation is faster.
Community
  • 1
  • 1
Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
  • I'm not sure I understand what you're saying... are you *really suggesting that the only use for private/public is to protect against someone misusing a data member? If so then I'd argue you're giving short shrift to scope and name space collision which are really pretty crucial in any large (or even small) project. And javascript has facility for private members, so clearly the language authors felt the same way about it. – Yevgeny Simkin Oct 10 '13 at 02:05
  • @GeniaS. Read my answer carefully. I did mention that JavaScript supports private variables via closures. All I am saying is that you don't need to keep everything private. Making properties public is much simpler than trying to make a private property accessible to only a certain class of objects. In most cases it doesn't even matter whether the property is public or private. Bothering too much about keeping your API cleaning is an unnecessary waste of time. Scope and name space collision? Are you telling me that you use the same name for two different variables in the same object? Explain! – Aadit M Shah Oct 10 '13 at 02:14
  • we're talking about inheritance, right? That's the OP's intention (she's talking about prototyping). In that context, specifically in Java, private members aren't inherited precisely because the user of the subclass might want/need to use the same labels for some other reason. Obviously it works differently in javascript; but the notion is the same. I can easily imagine someone wanting to use "id" as a label that holds some user specific value which is different from the superclass's design for what an id is. – Yevgeny Simkin Oct 10 '13 at 05:30
  • @GeniaS. No, we're not talking about inheritance. There's no mention of inheritance anywhere in the question or in any other answer. The OP's intention is to access the private property of one object from a method of another object. The OP is definitely not talking about prototyping. Either way inheriting public properties in JavaScript is not a problem. Inherited properties can be shadowed. Hence there is no scope or name space collision. – Aadit M Shah Oct 10 '13 at 08:04
  • @AaditMShah Thanks for the answer. I'm aware of how the JS prototype chain works (hence my differentiation of Java as a class-based language in the first line) but was hoping there was a better solution than to just "make it public". There are, of course, advantages to defining properties on the prototype instead of in a closure. My hiccup in this particular example is that the implementation (array of ints) is so different from the API (set of bits). As a small counterpoint to the documentation suggestion, a reflecting IDE would provide code completion even for undocumented prototype members. –  Oct 10 '13 at 14:55
  • @atonparker No don't define properties on the prototype. The prototype is only for methods, not for properties. Really bad things happen when you put properties on the prototype. It's alright for the implementation to be different from the API. The end user never needs to know. Even if the end user stumbles upon the implementation by mistake (e.g. through code completion in a reflecting IDE) it wouldn't cause any harm. If you feel too paranoid then it's conventional in JavaScript to prefix private property names with an underscore. This informs the end user not to mess with the property. Cool? – Aadit M Shah Oct 10 '13 at 16:18
  • Yes, thanks for the tips, accepted. And a silly aside: prototype methods *are* properties of the prototype! A property in JS is just a key/value pair of an Object. From [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects): "a method is a property of an object that is a function". –  Oct 11 '13 at 20:10
  • @atonparker True, but apropos to the context I'm using the word property to refer to non-function properties and the word method to refer to function properties. – Aadit M Shah Oct 12 '13 at 01:49