4

I've come across a javascript/jQuery design structure where each action was defined in an object literal, like this :

    if(typeof window.MYWEB === "undefined"){
        window.MYWEB = {};
    }

    MYWEB.Utils = {        
        doSthgUsingWinSize: function(){
            var width = $(window).width();
            //do something using this value
        },
        doSthgElseUsingWinSize: function(){
            var width = $(window).width();
            //do something else using this value
        }
    };

    //init:
    $(document).ready(function(){
        window.MYWEB.Utils.doSthgUsingWinSize();
        window.MYWEB.Utils.doSthgElseUsingWinSize();
    });

First question: Is this a form of 'module design pattern'? (Wherever I've looked to learn about the module pattern examples, there are anonymous functions and IIFEs, and I'm getting confused as to what makes a module pattern).

Second question: In the example above, I have var width = $(window).width() twice. In this 'pattern' I'm working with, how can I abstract $(window).width() as a separate function object, and pass the returned result into a variable that can be accessed by the other 2 functions? - this clearly isn't good enough (edit: to clarify, $(window).width() still runs twice - I want to store the width value once and using the value twice):

    MYWEB.Utils = {
            _getWindowWidth: function(){
            return $(window).width();
        },
        doSthgUsingWinSize: function(){
            var width = MYWEB.Utils._getWindowWidth();
            //do something using this value
        },
        etc
    }

Feel like I'm missing something fundamental here, but I can't quite find the words to google it! Any help or helpful pointers would be appreciated.

soba3
  • 389
  • 3
  • 11
  • 1
    `this clearly isn't good enough` .... why not? – charlietfl Jan 07 '15 at 16:55
  • 1
    I disagree with the close votes, particularly the ones claiming the question is opinion based. This is a module pattern, that is a fact, not an opinion. – Dexygen Jan 07 '15 at 17:02
  • 1
    i don't think it's a module because it's not self-contained, but i don't know how "official" that is – dandavis Jan 07 '15 at 17:08
  • 1
    @charlietfl I suspect s/he means it's not good enough because calling the helper function requires almost twice as many characters as the original `$(window).width();`. – JLRishe Jan 07 '15 at 17:19
  • @JLRishe but OP should make that clear by being more specific is the point. I agree with your assumption but it is just an assumption and the reference is not a proper problem statement – charlietfl Jan 07 '15 at 17:22
  • @charlietfl Ok, good point. – JLRishe Jan 07 '15 at 17:25
  • Thanks everyone, for the answers to the first question. – soba3 Jan 07 '15 at 18:21
  • @JLRishe: point taken, I just edited my question for clarity, thanks. – soba3 Jan 07 '15 at 18:27

3 Answers3

4

Answer to your first question: That's a module pattern. As Addy Osmani said in his article Patterns for Large-Scale JavaScript Application Architecture:

[...] a module pattern encapsulates 'privacy', state and organization using closures. It provides a way of wrapping a mix of public and private methods and variables, protecting pieces from leaking into the global scope and accidentally colliding with another developer's interface. [...]

Creating functions and data within an object, you are "protecting pieces from leaking into the global scope".

Answer to your second question: You can reach the width variable, setting it as an object property:

MYWEB.width = $(window).width();

If you want access it within the current context, you can do this:

MYWEB.Utils.width = $(window).width();
  • @soba3 It would depend on what you are trying to do, but I wouldn't recommend storing the window width in a property and continuing to access it thereafter. The window can change sizes and generally you'll want to get the width dynamically rather than referencing a static value. – JLRishe Jan 07 '15 at 20:45
  • @JLRishe That's a good point - mine was an off-the-cuff example, but I could've chosen a better one! Thanks. – soba3 Jan 08 '15 at 17:50
2

Yes, that is essentially a module pattern that you have there.

You can create your module with an IIFE in order to use private, shared variables and functions in it:

MYWEB.Utils = (function (window, $) {
    function getWidth() {
        return $(window).width();
    }

    function doSthgUsingWinSize() {
        //do something with getWidth()
    }

    function doSthgElseUsingWinSize() {
        //do something else with getWidth()
    }

    return {
        doSthgUsingWinSize: doSthgUsingWinSize,
        doSthgElseUsingWinSize: doSthgElseUsingWinSize
    };
})(window, jQuery);

Note that the same approach can be used to store and access a static value for width, but I would recommend against it for the reasons I mentioned in my comment under Leonardo Manrique's post. Here is how you would do that, though:

MYWEB.Utils = (function (window, $) {
    var width = $(window).width();

    function doSthgUsingWinSize() {
        //do something with width
    }

    // the rest is the same as above
})(window, jQuery);
Fuhrmanator
  • 11,459
  • 6
  • 62
  • 111
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • Thank you, yes I've seen this pattern before - so is there a consensus that my example module pattern is 'not recommended'(as was suggested by simon? – soba3 Jan 07 '15 at 18:55
  • @soba3 I'm not quite sure why he said it wasn't recommended. I think there are plenty of experienced developers who would use that pattern. One big benefit of the IIFE approach here in my answer is that it keeps the internal functionality and values unaccessable (and unmodifiable) to the outside world, but it also has a few (small) drawbacks. – JLRishe Jan 07 '15 at 20:51
  • Thanks for your input, I'll be looking into this pattern in more detail to fully understand and use it in the future. – soba3 Jan 08 '15 at 17:43
2

This is a basic module design pattern (not recommended) and will simply create a plain old javascript object, this will contain any default ECMAScript object methods. You are also able to access this when calling other methods in the same object.

if(typeof window.MYWEB === "undefined"){
    window.MYWEB = {};
}

MYWEB.Utils = {       
    _getWidth: function(){
        return $(window).width();            
    },
    doSthgUsingWinSize: function(){
        console.log(this._getWidth());
    },
    doSthgElseUsingWinSize: function(){
        console.log(this._getWidth());
    }
};

$(document).ready(function(){
    window.MYWEB.Utils.doSthgUsingWinSize();
    window.MYWEB.Utils.doSthgElseUsingWinSize();
});
Simon Staton
  • 4,345
  • 4
  • 27
  • 49
  • Hmm...the use of `this` was what I was looking for, as I wanted to keep the pattern rather than break out of it to set the variable outside of the `Utils` object - but are you saying that this is also not recommended? (or have I misunderstood?) – soba3 Jan 07 '15 at 18:48
  • Actually this use of `this` in fact was not what i was looking for, as it's still calling the function rather than inserting a value. My head just over-heated. – soba3 Jan 07 '15 at 19:03
  • @soba3 In the case of the window's width, I would say using a function is preferable to using a static value. Please see the comment I left on Leonardo's post, and the edit to my answer. – JLRishe Jan 07 '15 at 20:48