HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Namespaced JavasScript code

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
namespacedcodejavasscript

Problem

I have the following example app: http://dev.driz.co.uk/jsfunction/

Which runs two types of script files with the same outcome.

Script1:

var script1 = {

    showMessage: function( message ) { 

        var el = document.getElementById('example1');

        el.innerHTML = message;

    }
}


and script 2:

window.script2 = function() {

    function showMessage( message ) {

        var el = document.getElementById('example2');

        el.innerHTML = message;

    }

    return {

        showMessage: showMessage

    }

}();


They are both namespaced so I can them like:

window.onload = function() {

    script1.showMessage('Hello world!');

    script2.showMessage('How are you?');

};


But what's the better way forward? Script1 is the type I would normally write but it requires you to sometimes call a init function first if you have some events that need running on document load.

For example:

var script = {

    init: function() {

        // some events such as onlick etc..

    }

};

script.init();


Script2 however is a self executing function and therefore would get around this but being a function itself would it allow the same flexibility?

Any thoughts? Suggestions or examples of how people namespace there script files to make them neater and more efficient?

Solution

Try module-pattern, or somewhat like the module pattern, using an IIFE

In your case:

(function(ns){

  ns.showMessage = function(message){
    var el = document.getElementById('example1');
    el.innerHTML = message;
  }

}(this.script1 = this.script1 || {}));

window.onload = function() {
  script1.showMessage('Hello world!');
};


Here's the explanation

//basically, an IIFE is a function that executes itself
(function(ns){

  //in here, ns is a reference to our this.namespace

  //also, this IIFE provides us with a local scope
  //we can declare functions and variables that only this scope, by default, sees

  //a "private" variable
  var priv = "I can only be seen in the module";

  //a "private" function
  function privFn(){
    console.log('I am only usable in the module');
  }

  //a "public", or more accurately, an "exposed" variable
  //we attach it to the namespace
  ns.foo = 'I am an exposed value';

  //an exposed function
  ns.bar = function(){
    console.log('exposed!');
    //with an exposed function, we can also call a private function
    privFn();
  }

//this line creates the namespace or uses an existing one
//it then executes the function, passing the created/existing namespace
}(this.namespace = this.namespace || {}));


And so, using our module:

//we can use the exposed entities
namespace.bar(); 
//exposed! 
//I am only usable in the module <- since bar called privFn, it also prints
namespace.foo === 'I am an exposed value'

Code Snippets

(function(ns){

  ns.showMessage = function(message){
    var el = document.getElementById('example1');
    el.innerHTML = message;
  }

}(this.script1 = this.script1 || {}));

window.onload = function() {
  script1.showMessage('Hello world!');
};
//basically, an IIFE is a function that executes itself
(function(ns){

  //in here, ns is a reference to our this.namespace

  //also, this IIFE provides us with a local scope
  //we can declare functions and variables that only this scope, by default, sees

  //a "private" variable
  var priv = "I can only be seen in the module";

  //a "private" function
  function privFn(){
    console.log('I am only usable in the module');
  }

  //a "public", or more accurately, an "exposed" variable
  //we attach it to the namespace
  ns.foo = 'I am an exposed value';

  //an exposed function
  ns.bar = function(){
    console.log('exposed!');
    //with an exposed function, we can also call a private function
    privFn();
  }

//this line creates the namespace or uses an existing one
//it then executes the function, passing the created/existing namespace
}(this.namespace = this.namespace || {}));
//we can use the exposed entities
namespace.bar(); 
//exposed! 
//I am only usable in the module <- since bar called privFn, it also prints
namespace.foo === 'I am an exposed value'

Context

StackExchange Code Review Q#20928, answer score: 2

Revisions (0)

No revisions yet.