Search code examples
javascriptjqueryreliabilityside-effects

Enclosing external jQuery script


I have an external JavaScript file that will be used on pages with lots of other scripts. My script involves a lot of jQuery that listens for events, and by design, I have many global vars declared. I've been reading best practice articles, and a lot is said about 'polluting the global namespace' and inadvertent script interaction.

What's the best way to enclose (encapsulate?) my JavaScript file so that:

  • I can still access some of the variables outside of the enclosure
  • The jQuery event listeners will function properly

I'm not at liberty to disclose the code, so even general responses are appreciated. Additionally, any other tips on making scripts less vulnerable to other scripts on the page are welcome.

I've found enclosure styles for regular JavaScript, but does the use of jQuery complicate this?


Solution

  • Generally what this boils down to is encapsulating your objects into a "namespace". I use quotes there because the term is not an official semantic in JavaScript, but rather one that is achieved through basic object encapsulation.

    There are several ways to do this, and it ultimately comes down to personal preference.

    One approach is to just use a basic JS object, and keep everything in it. The name of the object should be semantic and give the object some meaning, but otherwise it's purpose is to just wrap your own code and keep it out of the global namespace.

    var SomeName = {
        alpha: 1,
        beta: {a: 1, b: 2},
        gamma: function(){ 
            SomeName.alpha += 1;
        }
    }
    

    In this case, only SomeName is in the global namespace. The one downside to this approach is that everything inside the namespace is public, and you have to use the full namespace to reference an object, instead of using 'this' - e.g. in SomeName.gamma we have to use SomeName.alpha to reference the contents of alpha.

    Another approach is to make your namespace a function with properties. The nice feature of this approach is you can create 'private' variable through closures. It also gives you access to closured functions and variables without full namespace referencing.

    var SomeName = (function(){
       var self = this;
       var privateVar = 1;
       var privateFunc = function() { };   
    
       this.publicVar = 2;
       this.publicFunc = function(){
           console.log(privateVar);
           console.log(this.publicVar); // if called via SomeName.publicFunc
    
           setTimeout(function(){ 
               console.log(self.publicVar);
               console.log(privateVar);
           }, 1000);
       };
    }();
    

    The other bonus of this approach is it lets you protect the global variables you want to use. For example, if you use jQuery, AND another library that creates a $ variable, you can always insure you are referencing jQuery when using $ by this approach:

    var SomeName = (function($){
        console.log($('div'));
    })(jQuery);