1

So before I always used this method of encapsulating my Javascript:

Classtype = (function (){
//private members

    var variable1;
    var variable2;

//

//public methods
    return {
        SetVariable1: function(pvariable){
        variable1 = pvariable;
        },

        GetVariable1: function(){
        return variable1;
        }

    };    
})();

$(document).ready(function(){

    Classtype.SetVariable1('var');
    var t = Classtype.GetVariable1();
    alert(t);
});

But today in my Javascript class, the teacher taught us the following:

function Cname(pvariable1, pvariable2)
{
//private members//
var variable1 = pvariable1;
var variable2 = pvariable2;

//Getter

this.Getvariable1=function() {
return variable1;
 }   
}

$(document).ready(function(){
var cname = new Cname('test1', 'test2');
var r = cname.Getvariable1();
alert(r);        
});

Since I'm pretty new to Javascript I was wondering which way of declaring classes/encapsulating my code is the preferred way and why?

Dimo
  • 3,238
  • 6
  • 29
  • 46
  • blah, that should be `Cname.prototype.Getvariable1 = function() {...}`. also, naming conventions! – tckmn Sep 09 '13 at 22:45
  • your teacher would be correct its simpler to do `var variable1 = pvariable1;` and you dont have to exit the function the variable are already there, easier for coders to understand, i dont think there is any real difference. (maybe his is a tiny bit faster - no search for variable but i dont think there is a difference) – Math chiller Sep 09 '13 at 22:46
  • They both work, it's all down to preference really. I'd personally prefer the second as it's simpler. – Overcode Sep 09 '13 at 22:46
  • There is not much difference but the yet unused prototype. Check [this answer](http://stackoverflow.com/questions/13418669/javascript-do-i-need-to-put-this-var-for-every-variable-in-an-object/13418980#13418980) for some explanation and examples with actual properties. In your example you're only using private variables yet. – Bergi Sep 09 '13 at 22:49
  • 1
    @tryingToGetProgrammingStraight: Much more simple would be to omit the `var` statments at all and use `function Cname(variable1, variable2) { /* all parameters are local variables */ }`. – Bergi Sep 09 '13 at 22:50
  • @Bergi you are right, and they also need new names here, that would definitely be faster (by approx one ten billionth of a second - lol). – Math chiller Sep 09 '13 at 22:53

2 Answers2

2

Preferred way of defining private variables/methods?

There is only one way, and it's the same in both of your snippets. You have a function scope in which variables are declared, and when the function is called their values are set. Any functions created in that scope can access them, even if the functions are called from outside (when they are exported from the scope, e.g. by returning them on an object).

What is the difference then?

There are two main aspects:

  • Your first pattern does immediately invoke the function and init your object with the public method - creating a "singleton". This is called the revealing module pattern. The second one does only define (create) a function that can be used multiple times, to instantiate many objects with similar shape. The invocation (with the ()) here is inside your dom-ready handler.
  • While the first pattern does yield a simple, plain object, the second one is a constructor function. When invoked with the new keyword, it will create an object that does inherit properties from the Cname.prototype object. You haven't created any properties on that, so it's empty except for the constructor property: cname.constructor == Object.getPrototypOf(cname).constructor == Cname.prototype.constructor == Cname. You will get into this prototypical inheritance in your lessons soon :-)
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • so basically, the first way is better for single use and the second for multiple use? – Dimo Sep 10 '13 at 08:19
  • 1
    Exactly. However, not every function for multiple use must be a constructor, sometimes functions that return plain objects are used as well. – Bergi Sep 10 '13 at 09:53
1

Bergi's answer sums it up well, but I just wanted to add that it is possible to combine both patterns without one shortcoming of either: Choosing an OOP pattern in javascript . Your teacher's example has the benefit of allowing for wholly independent instances of Cname (e.g., if you went on to add var cname2 = new Cname('test3', 'test4');, test1 would not be available inside cname2 and test3 would not be available inside cname), but it has the disadvantage of adding a function into memory (Getvariable1) for each of these independent instances. By declaring the getter function on the prototype (as in the linked example), this will only add one function into memory yet be available on all of those instances (although it, as with your teacher's example, adds too much overhead if you are sure you will only need one instance).

For your example, by the way, it is a good idea to declare Classtype with var, even if in global scope, since omitting declarations is disallowed by "strict mode", a more recent capability added to modern JavaScript engines to allow for faster and tighter coding (requiring 'var' in strict mode was presumably designed to avoid JavaScript's all-too-easy ability to create accidental globals).

Community
  • 1
  • 1
Brett Zamir
  • 14,034
  • 6
  • 54
  • 77