2

I am trying to write my javascript code using modular pattern, but i am facing problem while calling the functions inside and also there are some security problems. I can easily open the console and type in my namespace name . variable and change the variable value.

JS

Below JS Code is working fine, but as i said i can change the gridValue from console. How do i avoid this. i will be using this variable across all my functions.

    var myTicTacToe =  {
        turn:'X',
        score: {
            'X': 0,
            'O': 0
        },
        gridValue: 0,

        fnLoad:function () {
            var select = document.getElementById("grid");
            for (i = 3; i <= 100; i += 1) {
                var option = document.createElement('option');
                select.options[select.options.length] = new Option(i + ' X ' + i, i);
            }
        }
    }

window.onload = function(){
      myTicTacToe.fnLoad();
}

Below one is giving me problem while calling the fnLoad.

var myTicTacToe = function(){
    var turn = 'X',
        score =  {
            'X': 0,
            'O': 0
        },
        gridValue =  0,

    fnLoad = function () {
        var select = document.getElementById("grid");
        for (i = 3; i <= 100; i += 1) {
            var option = document.createElement('option');
            select.options[select.options.length] = new Option(i + ' X ' + i, i);
        }
    }
}

    window.onload = function(){
          myTicTacToe.fnLoad();
    }
  1. How can i protect my gridValue or any of the variable in First pattern ?
  2. Why i am not able to call fnLoad just like first one ? how do i call it ?
  3. Whats the difference between these 2 patterns ?
  4. In the first code when i declared any variable using var, it gave me error. Why is it so ?
  • possible duplicate of [JavaScript module pattern with example](http://stackoverflow.com/questions/17776940/javascript-module-pattern-with-example) – DoXicK Aug 25 '14 at 12:32
  • @DoXicK what about answer for 3rd and 4th question? – Sharath Bangera Aug 25 '14 at 12:40
  • 3 is something answered in many articles online about the module pattern. 4 i don't know, since you don't have an example. – DoXicK Aug 25 '14 at 12:42

3 Answers3

2

What you are referring to is the Revealing Module Pattern. Everything is private unless you explicitly return it

var myTicTacToe = (function(){
    var turn = 'X',
        score =  {
            'X': 0,
            'O': 0
        },
        gridValue =  0,

    fnLoad = function () {
        var select = document.getElementById("grid");
        for (i = 3; i <= 100; i += 1) {
            var option = document.createElement('option');
            select.options[select.options.length] = new Option(i + ' X ' + i, i);
        }
    };

    return {
        load: fnLoad //fnLoad is now publicly named "load".
    };
})();

window.onload = function(){
      myTicTacToe.load();
}

/* Or even
window.onload = myTicTacToe.load; //Because it's a single function.
*/

As for your concrete questions:

  1. You can't. All object members are public by default with the normal Module Pattern.
  2. Because you haven't returned it, see the example above.
  3. One allows for private members, and one does not. The revealing pattern allows for privates.
  4. I didn't understand which variable we are talking about. But if it's an object member, it should not be declared with a var.
Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308
  • What is the difference between first pattern and second pattern then ? one more question is myTicTacToe is now an anonymous block, which will get called as soon as JS is loaded rite ? will it not create problem cos document.getElementById("grid") i don't think DOM is loaded before . – Sharath Bangera Aug 25 '14 at 12:43
  • +1 for thinking alike, and linking that great article. – agconti Aug 25 '14 at 12:44
  • you forgot to execute your IIFE. you are missing *()* edit: aaanddd you just fixed it – DoXicK Aug 25 '14 at 12:44
  • @SharathBangera Basically, the first one is a simple object, and the second one is a self invoking function, where *the result* of which is an object. The second one allows you to define functionality without revealing it. As for whether or not it would be executed, the `fnLoad` function won't be executed until it's called with `myTicTacToe.load()`, only then will the DOM be queried. So you are safe to use it. – Madara's Ghost Aug 25 '14 at 12:46
  • @SecondRikudo But IIFF supposed to be called by itself rite ? how come here its working here differently ? sorry if i am asking foolish questions but i am new to all this functionalities. – Sharath Bangera Aug 25 '14 at 12:50
  • 1
    @SharathBangera You don't have to apologize for being a beginner. [Let's continue this discussion in chat](http://chat.stackoverflow.com/rooms/17/) – Madara's Ghost Aug 25 '14 at 12:51
1

You can use a closure to make gridValue a private variable. Consider this pattern:

var myTicTacToe =  (function(){
        var turn = 'X'.
            score =  {
                'X': 0,
                'O': 0
            },
            gridValue = 0;

        return {
            fnLoad: function () {
                  var select = document.getElementById("grid");
                  for (i = 3; i <= 100; i += 1) {
                      var option = document.createElement('option');
                      select.options[select.options.length] = new Option(i + ' X ' + i, i);
                  }
             }
        };
    })();

window.onload = function(){
      myTicTacToe.fnLoad();
}

Here we use an IIFE to close in the local variables so that only the fnLoad function has access to them. Later the fnLoad function is returned and invoked fill the namespace so it can be public ally accessed by other parts of your program.

This pattern can be extremely useful. Read more here: http://css-tricks.com/how-do-you-structure-javascript-the-module-pattern-edition/

agconti
  • 17,780
  • 15
  • 80
  • 114
  • your using a anonymous block here rite ? will thi be called even before window.onload ? – Sharath Bangera Aug 25 '14 at 12:38
  • @SharathBangera because the IIFE is assigned to myTicTacToe, the inner code will execute before window.onLoad() and the return value of fnLoad will be able to be accessed. – agconti Aug 25 '14 at 12:41
1

This links is my constant reference when working with javascript. It does an amazing job of explaining the different patterns to use with javascript and I bet will help solve your issue.

http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/#designpatternsjavascript

Here is your code refactored to protect your private variables and only allow methods to be public that you declare. I am using the "Revealing Modular Pattern" below.

var myTicTacToe = (function () {

    // PRIVATE AREA
    var turn = 'X';
    var score = {
        'X': 0,
        'O': 0
    };
    var gridValue = 0;

    function fnLoad() {
        var select = document.getElementById("grid");
        for (i = 3; i <= 100; i += 1) {
            var option = document.createElement('option');
            select.options[select.options.length] = new Option(i + ' X ' + i, i);
        }
    }

    // PUBLIC METHODS
    return {
        Load: fnLoad
    }

})();

then call it like

myTicTacToe.Load();

If you need to pass a dependency in such as jQuery or another module you've created then you would create the parameter in the (function(HERE) and then pass it in at the bottom in the last set of parentheses. Here is an example of your code with jQuery.

var myTicTacToe = (function ($) {

    // PRIVATE AREA
    var turn = 'X';
    var score = {
        'X': 0,
        'O': 0
    };
    var gridValue = 0;

    function fnLoad() {
        var select = $('#grid');
        for (i = 3; i <= 100; i += 1) {
            var option = document.createElement('option');
            select.options[select.options.length] = new Option(i + ' X ' + i, i);
        }
    }

    // PUBLIC METHODS
    return {
        Load: fnLoad
    }
})($);
Tony
  • 3,269
  • 1
  • 27
  • 48