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(){
;(function(){
// obviously, always have "var ..." when defining a variable (always)
var foo;
// nobody outside can see this var
function bar();
// 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.
var mymodule = mymodule || {};;(function(){// Constructorfunction 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("Animesh");
// get some properties
console.log("person name: " + person1.name());
// >>> will output >>> "Animesh"
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.function inherit(Child, Parent) {
var F = function() {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child._super = Parent.prototype;
Child.prototype.constructor = Child;
};
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 overwrite person methods with // Programmer.prototype.****
mymodule.Person = Person; mymodule.Programmer = Programmer; })(); // in the application code
var a = new mymodule.Person("Animesh");
var b = new mymodule.Programmer("Nanda","js");
console.log(a.constructor.name + " " + a.name() + " can code: " + a.canCode());
console.log(b.constructor.name + " " + b.name() + " can code: " + b.canCode() + " language: " + b.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
// --------- 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
With Regards,
Animesh Nanda
Sr.Software Engineer | Photon Infotech
Bengaluru | Karnataka | INDIA.
No comments:
Post a Comment