Building Enterprise HTML5 Application

JavaScript for Enterprise HTML5 Applications<

Mar 11, 2013, by Jeremy Chone

Myths v.s. Facts

Here are some JavaScript myths and "worst-practices" and their facts:

  • JavaScript is not Object Oriented.
  • JavaScript is object oriented, albeit, prototype based, but it is as good as class based OO, and best of all, with very few lines of code, you can make it “pseudo-class” as well.
  • Developers need a Sencha like Framework to do Object Oriented in JS.
  • Developers should do Object Oriented the JavaScript way and refrained to do it “a framework way.” See below for how to do clean, extensible, and simple Object Oriented programing the JavaScript way. Do NOT use JS wrapper like Ext.Define("Class",....) to do OO in JavaScript, it is not needed, and you will spend time learning the "framework" way rather than the JavaScript way.
  • JavaScript is not a robust language for application.
  • JavaScript is an extremely flexible language and, yes, developers can hang themselves with it. However it does not mean that JavaScript is not robust, it just means that developers need to be developers, and have good conventions, disciplines, and code design and they will realize that JavaScript is an extremely powerful language to write complex apps with simple code.

Top JavaScript Resources

JavaScript for Application: OO and Best Practices

So, here are some of our best javascript practices:

1) Almost always scope your JS code "immediate function"

JavaScript does not have code block scoping (with { ... }) but everything in a function is scoped. Consequently, when building a new module, always create an immediate function to scope all the properties and functions. This way, you can expose the public properties and methods/object types you want, and keep the rest visible only to this function body (this is very convenient for scoping).

// create the mymodule object if it does not already exists
// Note: this is global scope since it is outside of the immediate function  
var mymodule = mymodule || {}; 

// immediate function notation (start with ";" to make it semicolumn-less friendly)                    
;(function(){
  
  // obviously, always have "var ..." when defining a variable (always)
  var foo; // nobody outside can see this var
  
  function bar(); // nobody outside can see this var
  
  // this will be visible outside, since attached to mymodule. 
  mymodule.publicFun1 = function() {...};
  
  
})(); // execute the function immediately

Partition your code diligently with this technic to ease later refactoring. Do not hesitate to have multiple "immediate function block" in the same javascript file, the more atomic your code is, the more manageable it will become. Use clear commenting style to separate your different sections.

2) Object Type the JS Way with prototype

Here is the prototype way to create an Object Type.

// try to always scope your API, Object Types, properties in a namespace   
var mymodule = mymodule || {}; 

;(function(){
  
  // Constructor
  function Person(name){
    this._name = name; // as convention, ._*** is for privates properties
    // Note: there is a more robust way to do do private, but this will be for later
  }
  
  // A ObjectType Method
  Person.prototype.name = function(name){
    // Note: here, we use the js/jQuery style, setter/getter in one method
    if (typeof name === "undefined"){
      return this._name ;
    }else{
      this._name = name;
    }
  }
  
  // expose the Person "Object Type" in the mymodule namespace
  mymodule.Person = Person;
})(); 

// ... somewhere else in your js or page code

// create an instance of this Object Type
var person1 = new mymodule.Person("Mike");

// get some properties
console.log("person name: " + person1.name());

// >>> will output >>> "mike"

Note On Chrome at least, you can copy/paste the sample code blocks in the console, and it should run and output the message.

3) "Classical" Inheritance in JS

Here are 5 lines of code that you can add to your application, or use from some librairies (e.g., YUI, Brite, ...) to do a pseudo class inheritance with JavaScript. This is a very simple and convenient way to bring "classical" inheritance in JS (from JavaScript Patterns book).

/// In Brite, Brite.inherit
// or copy this function on top of your first .js file
function inherit(Child, Parent) {
  var F = function() {};
  F.prototype = Parent.prototype;
  Child.prototype = new F();
  Child._super = Parent.prototype;
  Child.prototype.constructor = Child;
};

// in annother file (preferrably)
var mymodule = mymodule || {}; 

;(function() {

  function Person(name) {
    this._name = name;
  }


  Person.prototype.name = function(name) {
    if( typeof name === "undefined") {
      return this._name;
    } else {
      this._name = name;
    }
  }


  Person.prototype.canCode = function(canCode) {
    if( typeof canCode === "undefined") {
      return this._canCode || false;
    } else {
      this._canCode = canCode;
    }
  }

  function Programmer(name,language) {
    Programmer._super.constructor.call(this, name);
    this.canCode(true);
    this.language(language);
  }
  // inherit Programmer with Person, call this after the Programmer constructor
  inherit(Programmer, Person);

  Programmer.prototype.language = function(language) {
    // sort version of the if/else
    return (typeof language === "undefined")?this._language:this._language = language;
  }



  // Note: Here you could override or ovewrite person methods with
  // Programmer.prototype.****

  mymodule.Person = Person;
  mymodule.Programmer = Programmer;

})();

// in the application code

var mike = new mymodule.Person("mike");
var nick = new mymodule.Programmer("nick","js");

console.log(mike.constructor.name + " " + mike.name() + " can code: " + mike.canCode());
console.log(nick.constructor.name + " " + nick.name() + " can code: " + nick.canCode() + " language: " + nick.language());

4) Private Methods

The immediate function code block and the javascript function methods function.call and function.apply are perfect to create private methods. Immediate function code block is also a great way to make utility functions, constants, default values, and cache visible only to a module or sub module.

var mymodule = mymodule || {};  

;(function(){
  
  // --------- Public API --------- //
  // Constructor
  function Chart(){
  }
  
  Chart.prototype.refresh = function(data){
    this._data = data;
    // we call the draw with the "this" context
    draw.call(this);
    // note: could use, "draw.apply(this,arguments)" if we wanted to pass all arguments 
  }  
  // --------- /Public API --------- //    

  // --------- Privates --------- //
  // only this function block can see the draw method
  function draw(){
    // ... some code that will draw
    // call the utilities functions
    
    console.log("drawing data: " + this._data);
  }
  // --------- /Privates --------- //
  
  // --------- Utility Functions & Values --------- //
  
  var color = {line:"#333",text:"#358"};
  
  function drawGrid(args) {
    // ....
  }
  // --------- /Utility Functions & Values --------- //
    
  mymodule.Chart = Chart;
})(); 

// somewhere in the code
var chart = new mymodule.Chart();
chart.refresh(["name1",345,"name2",654]);

// >>> will output >>> drawing data: name1,345,name2,654

Note Here we use a comment delimitator notation (// --------- sectionName --------- // and closing // --------- /sectionName --------- //) to slice the code clearly. We strongly recommend a similar notation for your code. Code "slicing" is a great way to improve your code readibility and help others getting up to speed quickly. Also, be consistent with your slice notation and naming convention.