6

I was reading this link http://addyosmani.com/largescalejavascript/#modpattern

And saw the following example.

var basketModule = (function() {
var basket = []; //private

return { //exposed to public
       addItem: function(values) {
            basket.push(values);
        },
        getItemCount: function() {
            return basket.length;
        },
        getTotal: function(){
            var q = this.getItemCount(),p=0;
            while(q--){
                p+= basket[q].price;
            }
        return p;
        }
      }
}());

basketModule.addItem({item:'bread',price:0.5});
basketModule.addItem({item:'butter',price:0.3});

console.log(basketModule.getItemCount());
console.log(basketModule.getTotal());

It stats that "The module pattern is a popular design that pattern that encapsulates 'privacy', state and organization using closures" How is this different from writing it like the below? Can't privacy be simply enforced with function scope?

var basketModule = function() {
var basket = []; //private
       this.addItem = function(values) {
            basket.push(values);
        }
        this.getItemCount = function() {
            return basket.length;
        }
        this.getTotal = function(){
            var q = this.getItemCount(),p=0;
            while(q--){
                p+= basket[q].price;
            }
        return p;
        }

}

var basket = new basketModule();

basket.addItem({item:'bread',price:0.5});
basket.addItem({item:'butter',price:0.3});
eirikrl
  • 438
  • 1
  • 5
  • 17

1 Answers1

4

In the first variant you create an object without the possibility to create new instances of it (it is an immediately instantiated function). The second example is a full contructor function, allowing for several instances. The encapsulation is the same in both examples, the basket Array is 'private' in both.

Just for fun: best of both worlds could be:

var basketModule = (function() {
   function Basket(){
        var basket = []; //private
        this.addItem = function(values) {
            basket.push(values);
        }
        this.getItemCount = function() {
            return basket.length;
        }
        this.getTotal = function(){
            var q = this.getItemCount(),p=0;
            while(q--){
                p+= basket[q].price;
            }
        return p;
       }
     }
   return {
     basket: function(){return new Basket;}
   }
}());
//usage
var basket1 = basketModule.basket(), 
    basket2 = basketModule.basket(),
KooiInc
  • 119,216
  • 31
  • 141
  • 177
  • I guess my question is now is the first pattern more "module" than the second. The link uses the first variant as an explicit example of the module pattern. – eirikrl Apr 28 '12 at 11:24
  • I'd say the first variant reflects the module pattern (delivering the `basketModule`), the second delivers a way to create `basket` *instances*. It's all a matter of labeling by the way, you could name the first variant also the 'singleton pattern'. – KooiInc Apr 28 '12 at 11:37
  • From the viewpoint that a module is an isolated package of functionality rather than a set of instantiatable classes, then yes. However the difference between the two isn't so much design, it's syntax. There's nothing stopping you from having a singleton the second way by having `var basketModule = new function(){...};`. The idea of using a return object is that you can condense the interface into a few lines of code if you prefer, so you can see it at a glance. But you wouldn't use large anonymous functions for this, you would just do `return {publicFunc:privateFunc};`. – Lee Kowalkowski Apr 28 '12 at 11:41
  • @eirikrl when it comes to the new keyword take a look at http://stackoverflow.com/questions/383402/is-javascript-s-new-keyword-considered-harmful for a nice discussion on the topic. TL;DR there are a lot of ways to do things in JavaScript and most of them are not strictly wrong. :) – Jonas G. Drange Apr 28 '12 at 11:46
  • Thanks...perfect explanations :) – eirikrl Apr 28 '12 at 11:49