1

**EDIT - this was not stated explicitly in the answers...but you can not have private members that are "templated (i.e. not copied for each instance)" with out a self executing function. You will pay with processor time and code complexity for privacy

Like a C++ private class member.

I've been trying to determine what the defacto "hack" is for creating classes Seems like there are over 10 ways people are defining classes.

The type of class I'm looking for provides privacy and modularization and a templating mechanism. Javascript has prototype to create this templating mechanism. However the solution I am currently using below does not have private members.

If there isn't I have to ask the question what is the cost if I move all my javascript to this class type...where each is a self executing function? Now when my code loads it all has to be run before it can be used.

This cost is a trade-off for better programming practice. Now I have proper classes with privacy.

Is the cost worth it? Is the extra run time worth the privacy?

Here are some similar questions:

Current Method - lacks privacy...is spread out..ie. not enclosed in parantheses

var Message = function( div ) 
{
    this.div = document.getElementById( div ); 
};

Message.prototype.messages = 
{ 
    name:       'Please enter a valid name',
    email:      'Please enter a valid email',
    pass:       'Please enter passoword, 6-40 characters',
    url:        'Pleae enter a valid url',
    title:      'Pleae enter a valid title',
    tweet:      'Please enter a valid tweet',
    empty:      'Please complete all fields',
    same:       'Please make emails equal',
    taken:      'Sorry, that email is taken',
    validate:   'Please contact <a class="d" href="mailto:support@host.com">support</a> to reset your password'
};

Message.prototype.display = function( type ) 
{
    Control.sendInner( this.div, this.messages[type] );
};
Community
  • 1
  • 1
  • Your edit doesn't make any sense at all. Let's look at the comparison. A self executing function for your class is a cost of 1. Calling a WeakMap to get private date is a cost of 100. Store all your data in closures does increasing memory usage per object is a cost of 100. It's not the SEF that's expensive. it's the run-time lookup in the weakmap or the run-time memory overhead per instance that's expensive – Raynos Dec 24 '11 at 20:52
  • Javascript does not support the efficient use of OO concpets like privacy and templating...this is evident from forums and from books, try the latest O'reilly on Javascript. It can be done but with additionall syntax and processing time. Wether or not to implement is up to the needs of the programmer. –  Jan 25 '12 at 17:23
  • I disagree, what do you define as "templating" – Raynos Jan 25 '12 at 20:56

4 Answers4

4

Javascript has prototype to create this templating mechanism. However the solution I am currently using below does not have private members.

The only mechanism I know of to use prototypes and privates states are WeakMaps.

This basically involves having a local WeakMap in scope of your prototype

Disclaimer: WeakMaps are ES6 , I belief currently only firefox 6 has an implementation, However they can be shimmed

var Message = (function() {
    var map = new WeakMap();

    var Message = function(div) {
        var privates = {};
        map.set(this, privates);
        privates.div = document.getElementById(div);
    };

    Message.prototype.messages = {
        name: 'Please enter a valid name',
        email: 'Please enter a valid email',
        pass: 'Please enter passoword, 6-40 characters',
        url: 'Pleae enter a valid url',
        title: 'Pleae enter a valid title',
        tweet: 'Please enter a valid tweet',
        empty: 'Please complete all fields',
        same: 'Please make emails equal',
        taken: 'Sorry, that email is taken',
        validate: 'Please contact <a class="d" href="mailto:support@host.com">support</a> to reset your password'
    };

    Message.prototype.display = function(type) {
        var privates = map.get(this);
        Control.sendInner(privates.div, this.messages[type]);
    };

    return Message;
}());

Note that WeakMaps are ES6 and that there is a significantly computational overhead to get objects from a weakmap rather then from this.

I have an article about emulating WeakMaps - Prototypes and privates state

Using the klass utility mentioned in the article the code would look like:

var Message = klass(function(privates) {
    return {
        constructor: function(div) {
            privates(this).div = document.getElementById(div);
        },
        messages: {
            name: 'Please enter a valid name',
            email: 'Please enter a valid email',
            pass: 'Please enter passoword, 6-40 characters',
            url: 'Pleae enter a valid url',
            title: 'Pleae enter a valid title',
            tweet: 'Please enter a valid tweet',
            empty: 'Please complete all fields',
            same: 'Please make emails equal',
            taken: 'Sorry, that email is taken',
            validate: 'Please contact <a class="d" href="mailto:support@host.com">support</a> to reset your password'
        },
        display = function(type) {
            Control.sendInner(privates(this).div, this.messages[type]);
        }
    };
});

Again using privates(this).x instead of this.x has a computational overhead of two function calls. this should not be ignored.

Also note that using weakmaps has significantly less memory overhead then using closures since your still using prototypes for functions and only using weakmaps for state.

Is the cost worth it? Is the extra run time worth the privacy?

Personally I say run-time penalty for 'privacy' is something that needs to be benchmarked. The overhead computationally is small and the overhead in memory usage is also small.

Raynos
  • 166,823
  • 56
  • 351
  • 396
  • There are no weak maps in your 2nd example...is it necessary to keep t he retrun above messages? –  Dec 24 '11 at 20:12
  • @stack.user.0 they are the same way. The 2nd is a little utility function that adds sugar and keeps your code DRY. You would have to read the article to follow what it does. `privates` is effectively a weakmap and `privates(this)` is effectively `map.get(this)` – Raynos Dec 24 '11 at 20:13
  • @stack.user.0 self excuting function is only cost for creating the 'class'. Class creation is only done once and is thus a very very minimal cost. You can take my word for it that compared to the script downloading time, script execution time is neglible. – Raynos Dec 24 '11 at 20:20
  • ... 20 function call overheads? That's what 20ps? Stop micro optimizing. – Raynos Dec 24 '11 at 20:32
0

So, the form I use is this:

var Message = function (div) {
    this.div = document.getElementById(div);
    // messages will be 'private'
    var messages = { 'name' : 'Please enter ...' }; // You get the picture here

    this.display = function (type) {
        Control.sendInner(this.div, messages);
    }
}

You can read more about private, static and public variables in this post under the Object Scope header.

Update: You can also use Strict Mode and set non-writable variables, or a getter only value. Though, this is not well supported as you might hope, and will probably cause you to be a lot stricter in how you write your code.

LoveAndCoding
  • 7,857
  • 2
  • 31
  • 55
  • @stack.user.0 Updated it with another way of doing it, but it isn't well supported yet. It would be a more forward looking idea than anything else... – LoveAndCoding Dec 24 '11 at 19:49
  • Javascript does not support the efficient use of OO concpets like privacy and templating...this is evident from forums and from books, try the latest O'reilly on Javascript. It can be done but with additionall syntax and processing time. Wether or not to implement is up to the needs of the programmer. –  Jan 25 '12 at 17:25
  • @stack.user.0 It's true. If I remember correctly they are trying to rectify this in the next version, but it is prototype based language, so traditional OOP concepts don't necessarily map very well. – LoveAndCoding Jan 25 '12 at 19:09
0

In your constructor any variable you declare within that function is effectively private - it's scoped to that instance only, i.e.:

var Message = function( div ) 
{
    var private = "hello, world!";
    this.div = document.getElementById( div ); 
};

However, these variables are so private that they can't be accessed from functions that you subsequently add to the prototype.

The only way to access them is via so-called "privileged methods", i.e. ones created as properties of this inside the object.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • so templated (prototyped) private variables do not appear to exist with out using self-executing functions? –  Dec 24 '11 at 19:43
  • By definition a private variable cannot be part of the prototype - the prototype is shared amongst _all_ instances. A prototyped variable is more like a "class static" variable from other OO languages. Privacy can only be achieved through scoping. Self execution is something else entirely, and not required. – Alnitak Dec 24 '11 at 19:47
  • How do I use scoping to make messages(in my example above) private? This is the holy grail I've been trying to find? They only need to be accessed from the public function display and that is it. –  Dec 24 '11 at 20:00
  • I really does help to just say 'you can have local variables and you can return a local object from a function' rather then dance around with '_so_ private' and 'privileged methods' – Raynos Dec 24 '11 at 20:10
  • @stack.user.0 so put them in as a variable _within_ that function! – Alnitak Dec 24 '11 at 20:57
  • Javascript does not support the efficient use of OO concpets like privacy and templating...this is evident from forums and from books, try the latest O'reilly on Javascript. It can be done but with additionall syntax and processing time. Wether or not to implement is up to the needs of the programmer. –  Jan 25 '12 at 17:25
0

I don't believe any kind of privacy is possible in JavaScript except via using scoping rules for variables. This doesn't always mean an immediately-invoked function expression, though. You can use constructor-scoped variables combined with constructor-assigned methods, like this:

function YourConstructor() {
    var private1 = 0,
        private2 = 'spock';

    this.count = function () { return private1++; }    
    this.chiefOfficer = function (name) { 
       if(name) private2 = name;
       return private2; 
    }
}

and even if you execute code before YourConstructor is defined, there's forward declaration magic that takes place and everything's fine (note: some of the other solutions posted use the var YourConstructor = function () {... idiom -- these won't work in situations where forward declaration is required).

There's one issue with this: you're defining your constructor-assigned methods every time you invoke your constructor (rather than once in assignation to the prototype). There may be a performance/memory hit for cases where you're creating a lot of these objects.

A word about privacy, though: I'd invite you to consider the opinion that most of the time, the need for privacy via a runtime-enforced mechanism is overrated.

Why? Developers have a lot to do; in all likelihood, they'd probably rather not have to pay attention to the internals of any given abstraction unless it leaks something noxious.

Classes that don't cause problems, that throw/return useful errors, that provide genuinely useful methods that you can call to get things done (vs lots of getters and setters!), and are documented well enough... these kind of classes probably won't need any kind of privacy enforcement mechanism because everyone will be so happy with the work your classes are saving them they won't ever peer inside.

For classes that don't meet that standard, the lack of a privacy enforcement mechanism may not be the real problem.

There is an exception to this: sometimes (particularly on a mashable web) you have code from untrusted sources mingling with yours. In a very dynamic language (like JavaScript), you may want to isolate/hide certain functionality in places where outside code can't get to it. If you're not worrying about this, though, you may want to spend more time encouraging implementation hiding/privacy socially via good design and documentation, less worrying about technical enforcement.

Weston C
  • 3,642
  • 2
  • 25
  • 31
  • privacy provides encapsulation...which is considered good programming practice...period....javascript does not have a standard mechanism to produce this like other languages....C++ private class member...or PHP private class member...This is why I'm having a hard time writing javascript...so much effort to produce what in antoher language you can use...two keywords class and private....To not get held up on this I'm just going to write my js as a collection of public static methods...later if the language supports class and private I'll update. –  Dec 24 '11 at 20:21
  • But is eeems the lerning curve is actually steeper for js than php and C++ b.c. you have to learn how to create "class" and "private" instead of just using them...+ you have to consider the performance costs of using these methods –  Dec 24 '11 at 20:24
  • 'you may want to isolate/hide certain functionality in places where outside code can't get to it' you can't really do that without a heavy sandbox around third party code. And if your using a heavy sandbox you don't need privacy. – Raynos Dec 24 '11 at 20:24
  • 1
    @stack.user.0 In javascript you just do `this._IAmInternal`, tada privacy enforced by naming convention. You don't need a compiler to enforce privacy for you. – Raynos Dec 24 '11 at 20:25
  • "encapsulation...which is considered good programming practice...period" Sure, encapsulation can be helpful, but not because it's inherently "good" -- rather, it's an organizing principle that's meant to help developers by providing an abstraction that's reusable and only coupled to the context in which it's used through a set of well-defined methods. The question is how much these benefits require a `private` keyword and compiler/runtime enforcement in order to be realized. – Weston C Dec 24 '11 at 22:55
  • I would argue that it is inherently good and that it is how you should program...everthing is private..and then make public only what others need access to. This helps with abstracion (and hence readability), security, and consistency across languages...alot of my javascript I have alreday written in PHP....that's my two cents. –  Jan 04 '12 at 18:01