kkudi
kkudi

Reputation: 1645

How to not re-define variables in javascript

Every time I invoke Client2.config.select2() everything is getting redefined.

Is there a way to prevent the re-definition of such an function/object? I.e. if I wanted to have another variable which saves some elements within this object, running Client2.config.select2() would override it.

Is there a well-known pattern to do this?

Client2.config.select2 = function() {

    var coreIDs    =  ['clientID', 'cptyID' , 'sym'];

    var nonCoreIDs =  ['groupBy','groupBy_impact_1','groupBy_impact_2',
        'groupBy_impact_3','groupBy_impact_4'];

    //non dynamic filters 
    var autoCompleteSettings =  function () {
        return {
            allowClear : true,
            minimumInputLength : 2,
            multiple : true,
            placeholder: "Select ",
            closeOnSelect : false,
            openOnEnter : true,
            ajax: {
                url : "../my?page=search",
                dataType : 'json',
                data : function(term, page) {
                    return {
                        q : term
                    };
                },
                results : function(data, page) {
                    return {
                        results : data
                    };
                }
            }
        };
    };

    var multipleSettings = function () {
        return {
            placeholder : "Select ",
            allowClear : true,
            closeOnSelect : false,
            maximumSelectionSize: 6
        };
    };

    return {
        getAutoCompleteSelectSettings: function() {
            return new autoCompleteSettings();
        },
        getMultipleSelectSettings: function() {
            return new multipleSettings();
        },
        getCoreSelect2IDs: function () {
            return coreIDs;
        },
        getNonCoreSelect2IDs: function () {
            return nonCoreIDs;
        },
        getSelect2IDs : function() {
            return coreIDs.concat(nonCoreIDs);
        }
    }
};

Upvotes: 2

Views: 137

Answers (3)

Rick Hanlon II
Rick Hanlon II

Reputation: 21667

You can do this using closures.

Essentially, you're going to set Client2.config.select2 equal to an immediate function, define your variables inside of the immediate function (which are assigned once), and use closure to access those once-defined variables inside of the function which is returned.

Client2.config.select2 =  (function() {                              /* 1 */

    var coreIDs    =  ['clientID', 'cptyID' , 'sym'];                /* 2 */

    var nonCoreIDs =  ['groupBy','groupBy_impact_1','groupBy_impact_2',
        'groupBy_impact_3','groupBy_impact_4'];

    //non dynamic filters 
    var autoCompleteSettings =  function () {
        return {
            allowClear : true,
            minimumInputLength : 2,
            multiple : true,
            placeholder: "Select ",
            closeOnSelect : false,
            openOnEnter : true,
            ajax: {
                url : "../my?page=search",
                dataType : 'json',
                data : function(term, page) {
                    return {
                        q : term
                    };
                },
                results : function(data, page) {
                    return {
                        results : data
                    };
                }
            }
        };    
    };    

    var multipleSettings = function () {
        return {
            placeholder : "Select ",
            allowClear : true,
            closeOnSelect : false,
            maximumSelectionSize: 6
        };
    };

    return function (){                                              /* 3 */
        return {
            getAutoCompleteSelectSettings: function() {
                return new autoCompleteSettings();
            },
            getMultipleSelectSettings: function() {
                return new multipleSettings();
            },
            getCoreSelect2IDs: function () {
                return coreIDs;
            },
            getNonCoreSelect2IDs: function () {
                return nonCoreIDs;
            },
            getSelect2IDs : function() {
                return coreIDs.concat(nonCoreIDs);
            }
        }
    }
})();

In (1) you see that we're wrapping the function like this:

(function(){ 
    /* ... */ 
})();

If you don't know, this is called an immediate function because it is executed immediately when it is reached. This means that this function runs once.

In (2) we're defining all the the variables you want defined once, once, inside the scope of the immediate function. Again, using closure you'll be able to access these variables in the returned function below.

In (3) we're having the immediate function return a function, which returns the object you wanted to return. When you access, say, getAutoCompleteSelectSettings then you will return autoCompleteSettings from inside the immediate function.

Essentially you can think of it like this. After the immediate function runs, we have defined the assignment like this (because this is what the immediate function returned):

Client2.config.select2 = function (){
    return {
        getAutoCompleteSelectSettings: function() {
            return new autoCompleteSettings();
        },
        getMultipleSelectSettings: function() {
            return new multipleSettings();
        },
        getCoreSelect2IDs: function () {
            return coreIDs;
        },
        getNonCoreSelect2IDs: function () {
            return nonCoreIDs;
        },
        getSelect2IDs : function() {
            return coreIDs.concat(nonCoreIDs);
        }
    }
}

And each of the Objects and variables we're accessing here are accessible through reference in the immediate function.

Upvotes: 2

BAD_SEED
BAD_SEED

Reputation: 5056

Have you ever tried const keyword?

Upvotes: 0

BenM
BenM

Reputation: 4278

You should use the module pattern: http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html

An example of this is:

(function (CkSpace, $, undefined) {
    CkSpace.GetLoanValues = function () { //public member
       //Do Stuff
    }
    var myNumber = 1; //private member

} (window.CkSpace = window.CkSpace || {}, jQuery));

Upvotes: 3

Related Questions