About Javascript Best Practices, ECMAScript 5

2015/12/2910 min read
bookmark this
Responsive image

Following is about javascript ECMAScript 5.

Javascript render in the browser

It should be good that use external scripts by default and sometime inline scripts. Should avoid use event driven scripts or dynamically loaded scripts.

inline scripts

Some time we write inline script.

<script>
var inline = function(){
return "hi";
};
</script>

external scripts

But we should try to move all javascript as external js file.

<script src="http://google.com/external.js" type="text/javascript">
</script>

deferred scripts

You might want to load javascript as delay which after page load.

<script src="http://google.com/external.js" defer="defer">
</script>

event driven scripts

We should avoid use like this.

<p onclick="myh3Clicked()">sample</p>

dynamically loaded scripts

Also, should avoid load js like this too.

var head= document.getElementsByTagName('head')[0];
   var script= document.createElement('script');
   script.type= 'text/javascript';
   script.src= 'helper.js';
   head.appendChild(script);

With

Should avoid use With, see MDN - With


//example use
//not good
with (document.head.style)
{
cssText = "test";
alignContent = "testContent";
}

// good
var headStyle = document.head.style;
headStyle.cssText = "test";
headStyle.alignContent = "testContent";

Javascript module patterns

Pattern #1 - revealing module pattern

I like this, because you'll get namespace of javascript, avoid global scope. Also, you will get encapsulation. In additional, I changed the minification for js that anything between START-UNITEST and END-UNITTEST will remove from javascript file. But when you reference it from your unit test file, you can call the method for your testing. The most important to me are, easy to see what's private, public, where's the function and variables. 


// anonymous express function, which will execute immediately and any method inside this scope will contains privacy as closure. var yourModule = (function($, _otherJs) { var _private1 = function(){ return "hi"; }; var _private2 = function(number) { return number * 10; }; var _importantPrivate = function() { // Doing crazy, important stuff. }; // return module as public interface return { // START-UNITTEST TEST1 : _importantPrivate, // END-UNITTEST calc1 : _private2, get : _private1 };
// here you define what dependency module used at here })(jQuery, otherJs);

List of pattern of using module design patterns


// Good
var myModule = (function(){

var _private = function(){
};

return {
 public : _private
};
})();

// Good
var myModule = (function(){

var _myModule = {};

var _private = function(){
};

_myModule.public = _private;

return _myModule;

})();

// Good
var myModule = (function(_myModule){

var _private = function(){
};

_myModule.public = _private;

return _myModule;

})(myModule);

or 
// Good
(function(_myModule){

var _private = function(){
};

_myModule.public = _private;

return _myModule;

})(myModule);

or 
// Good
var module = (function(_myModule){

var _private = function(){
};

_myModule.public = _private;

return _myModule;

})(module || {});

Following code is return everything at the end, it's hard to see the code and change or modulize the functions. I don't like doing in this way.


// Not good
(function() {
var _private = function() {
};

return {
public: function() {
 return "some logic";
},
public2 : function() {
 return "hi";
},
public 3 : function () {
},
// keep going with lots of more public method
}

})();

Inheritance by using module pattern


var firstModule = (function(){

var _private = function() {
return "hi";
};

return {
public : _private
};
})();

var overrideFirst = (function(_firstModule) {

var myOverrided = _firstModule;
myOverided.public = function() {
return "hello";
};

return myOverrided;
})(firstModule);

sub module or module pattern with namespace

I think this should be good for big organization to use as module patterns

// module.js
var module = (function()){
return {
};
})();

// module.child.js module.child = (function()) { return {}; })();
// module.child.son.js module.child.son = (function()) { return {}; })();
// module.child2.js module.child2 = (function()) { return {}; })();

New line at end of Javascript file

New Line Necessary

General reason is like following comment without new line, your javascript will break. But I think lots of bundling & minification library already handler this case. I wonder if there're any other case should use new Line.


asfda = "asdf"; // comment function method() {

.jshintrc

Global

avoid define as global in Javascript.

To avoid, i'm trying to use module pattern and closures.


// not good
// what's issue? so person A defined call() and will return 1000.
function call(){
// some work
return 1000;
}

// after load above script, let's assume your page load following script which use the same method name.
function call(){
// some work
return true;
}

// and this will return true.
call();

However, there're many ways.


// not good
// although you can define as namespace, but will be huge list and hard to see the code.
// and everything are accessiable.
var myModule = {
method1: function(){
return 1000;
},
method2: function(){
return true;
}
}

// not good
// this is use Revealing Module Pattern wich i use a lot and like it, but I don't like it return all the function at the end. It will end up hard to see at the last part and hard to differenitate what are public and private what could be move to shared location.
var myModule = function() {
var _private = {};
var _privateMethod = function(){
};

return {
   publicMethod : function(){
    return 1000;
   },
   publicMethod2 : function(){
    return true;
   }
}

}();

// good
var myModule = function($, otherSvc){
"use strict"; var _privateMethod = function(){ return 1000; }; var _privateMethod2 = function(){ return true; } return { public1 : _privateMethod, public2 : _privateMethod2 }; }(jQuery, otherService); // will return 1000; console.info(myModule.public1);

Strict mode

Strict mode will check certain syntax error in javascript. I'll try to put the "use strict" first line of the module.


var myModule = function(){
"use strict";
var _privateMethod = function(){
return 1000;
};


return {
public1 : _privateMethod
};

}();

For more information about strict mode in javascript, you can reference following links.

for

Foreach for arrary
array.forEach(function(item, i){

});

// one way
var list = [];
for (var i=0;i<list.length;i++){
// do some stuff here
}

// another way
var i,
length = 100;
for (i = 0; i < length; i++) {
// do work
}

// or following...
var i = 0,
length = 100;
for (; i < length; i ++) {
// do work
}

// or
var item;
for (item in objectList) {
// do work
}

// not good
// try avoid write one line code, first hard to read and also you// never know when it will be more than one line.
for (var i=0;i<100;i++) dowork();

if/else

 // normal way is, write two condition
if (condition) {
// true work
}
else {
// false work
}

// or better way, i think this is better readable, don't contain
// 'else'
if (condition) {
// do work
return;
}
// do another work

// or another way of shorthand.
var result = (condition) ? something() : somethingElse();

// or if you just need to know true/false of your condition
var result = (test > 1000);

javascript shortHand

 // before
var test;
if (condition) {
test = true;
}
else {
test = false;
}

// after
var test = (codition);

// before
// check Null, Undefined, Empty
var myStr2;
if (myStr !== null || myStr !== undefined || myStr !== '') {
myStr2 = myStr;
}

// after
var myStr2 = myStr || '';

// or
// before
if (myStr !== null || myStr !== undefined || myStr !== '') {
// do work
}

// after
if (myStr || '') {
// do work
}

// object arrary notation
// before, very old school way
var myArrary = new Arrary();
myArrary[0] = "1";
myArrary[1] = "a";

// after
var myArrary = ["1", "a"];

// or nother
var myArrary = new Arrary();
myArrary['test'] = "a";
myArrary['test1'] = "b";

// after
var myArrary = {
'test' : "a",
'test1' : "b"
}

// declare variable
// before
var a;
var b;
var c;

// after
var a,b, c;

// before
for (var i = 0; i < list.length; i++) {
}

// after
for (var i in list) {
}

// before
// get string's char
"string".charAt(0);

// after
"string"[0];

// short function calling
// before
if (condition) {
c_true();
}
else {
c_false();
}

// after
((condition) ? c_true : c_false)();

// switch statement
// before
switch (condition) {
case a:
doA();
break;
case b:
doB();
break;

}

// after
var switchCase = {
a: doA,
b: doB
};

if (switchCase[parameter]) {
switchCase[parameter]();
}

// zero number
// before
var x = 10000000;

// after
var x = 1e7;

jQuery


// prefix with $
// not good
var name = $(".name");

// good
var $name = $(".name");

// cache jquery object, why? access DOM element is expensive
// not good
$(".name").hide();
$(".name").show();

// good
$name = $(".name");
$name.hide();
$name.show();

Types

  • String
  • Number
  • Boolean
  • Arrary
  • Object
  • Undefined

Other - NaN is not a number, when you do "af" - "afs" will return NaN; Undefined type is Undefined; empty string "" is string type; null is Object type.

Objects

use {}following to create object.

// not good
var objectVar = new Object();
// good
var objectVar = {};

Arrarys

Use following syntax when deal with arrary.


// Use push to add value to arrary
var someList = [];
someList.push("hi");
someList.push("hello");
// console.info(someList); display -> ["hi", "hello"]

Declares

// better
// this way faster to load javascript, save few keystrokes, 'one'// var so better to read. var myString = "", myNumber = 0, myArrary = [], myObject = {},
myRegex = /()/,
myFunction = function(){};

// or
var myString,
myNumber = 100;
myString = true;

// or
var myStr1 = "",
myNum = 0,
myDate;

// not good
var mystr1 = "";
var myStr2 = "";
var myNum1 = 0;
var myDate;

Javasscript ShortCut



// not good
var name = "";
if (name !== '')
{

}

// good
if (name)
{}

// not good
if (name.length > 0){
}

// good
if (name.length)
{
}


Declare Functions


// named function declaration
function testFunc(para1, para2) {
}

// call function
testFunc("test", "asfd");

// named function with call back
function testFunc(para1, callback) {
callback(para1);
}

// call function
testFunc("tefa", function(para1) {
}

// anonymous function expression
var test = function() {
return true;
}

// named function expression
var test = function test() {
retu
}

Semicolons


// safety, in case two self-invoking function have no semicolons.
;(function() {
// some logic.
})();

However, I'm still not sure should I use ! or ; to define module function.


!(function() {
'use strict'; // some logic. })();

Name conventions


// private property us underscore
this._name = "name";

// define private this use underscore
var _this = this;

Reserved Words

Don't use reserved words, see Javascript Reserved words

HttpGet

Http Get - JSON Response
var request = new XMLHttpRequest();
request.open('GET', '/url', true);

request.onload = function() {
  if (request.status >= 200 && request.status < 400) {
    // Success!
    var data = JSON.parse(request.responseText);
  } else {
    // http status code not 200 and 300.
  } 

// more standard see -> https://xhr.spec.whatwg.org/
request.onerror = function() {
};

request.send();
Http Get - Request
var request = new XMLHttpRequest();
request.open('GET', '/url', true);

request.onload = function() {
  if (request.status >= 200 && request.status < 400) {
    // Success!
    var data = request.responseText;
  } else {
   // http status code not 200 and 300.
  }
};

// more standard see -> https://xhr.spec.whatwg.org/ request.onerror = function() {
}; request.send();

More info about XMLHttpRequest

 

HttpPost


var request = new XMLHttpRequest();
request.open('POST', '/url', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.send(data);
References for Javascript - Reading
References for Javascript - Reading

confusing, bugs