Tuesday, May 3, 2011

javascript namespace

Javascript namespace is nothing but actually a global object and all other variables, functions, objects are placed in this object, so they become properties of the global object.

Code below creates two global objects:

// we have two global objects
var Category = {
     name:'books', 
     description:'all books',
     getName : function(){return this.name;},
};
var Product = {};


Now let's introduce namespace, so everything is into MyProject namespace, and MyProject is the only global variable.

var MyProject =  MyProject || {};
MyProject.Modules = MyProject.Modules || {};
MyProject.Modules.Category = {
     name:'books',
     description:'all books',
     getName : function(){return this.name;},
};
MyProject.Modules.Product = {};


What if we want to use constructor function? We can still do that:

MyProject.Models.Car = function(model) {
       this.model = model;
}
var newCar = new MyProject.Models.Car('toyota');


It is tedious every time we declare a new namespace, we have to do something like

MyProject.Modules =  MyProject.Modules || {};


Let's create a general purpose namespace function

var MyProject= MyProject || {};
MyProject.ns = function (nsName) {
     var parts = nsName.split('.'),
     parent = MyProject,
     i;
    // strip redundant leading global
    if (parts[0] === "MyProject") {
         parts = parts.slice(1);
    }
    for (i = 0; i < parts.length; i += 1) {
          // create a property if it doesn't exist
         if (typeof parent[parts[i]] === "undefined") {
             parent[parts[i]] = {};
         }


         parent = parent[parts[i]];
    }
return parent;
};


Now, we have a general purpose namespace function. How to use it? At top of your javascript file, declare the namespace using this function.

//in file MyProject/Models/Car.js
MyProject.ns('Models');
MyProject.Models.Car = {};

//in file MyProject/Modules/Products/Kindles/Wifi.js

MyProject.ns('Modules.Products.Kindles');
MyProject.Modules.Products.Kindles.Wifi = {};


Well, if we think the prefix MyProject.Modules.Products.Kindles is too long, we can simply do

var ns = MyProject.ns('Modules.Products.Kindles');
ns.Wifi = {};


In extjs, declaring a namespace is simple as Ext.ns('SomeNamespacesStringWithDotConnection'); 



Basically that is the whole idea of javascript namespace. Actually, JavaScript doesn’t have namespaces built into the language syntax, unlike java or PHP5.3. But the key is, javascript's object (function is object as well) can provide local scope, so just put everything into your own object, and you can achieve namespace feature.

Friday, April 29, 2011

Too much flexibility in programming language, good or bad?

PHP is a very flexible programming language, and javascript is worse. I use the word 'worse' and i think that presents my point regarding language flexibility.

Too much flexibility usually means you can achieve same goal through variant ways. My point of view, that can only bring confusion. I guess that is one reason why software engineering stress so much on convention like naming convention and coding convention.


var person = {name:'henry', gender:'m'};


The code define a variable, person. Obviously, here person is an object. So we can access its name property through:

 person.name


Well, and you probably know that we can get the same result by calling

person['name'].


For me, that brings nothing but confusion. Let's see another example. The code below works very well:

function func() {
     return {name:'henry'};
}
//you will see Object { name="henry" } in console
console.log(func());


This also works as well:

//there is no semicolon!!!!
function func() {
     return {name:'henry'}
}
//you will see Object { name="henry" } in console
console.log(func())


See the difference? The second code snippet doesn't have semicolon! Javascript will add semicolons for you!
But check this code:
function func() {
     return 
     {
           name:'henry'
     }
}
//you will see undefined
console.log(func())



What do you expect from the above code? You are wrong if you think you still get an object. Actually, you will get undefined! Thanks to the javascript semicolon insertion mechanism, the code is actually like this:
function func() {
     return ;
     {
           name:'henry'
     }
}
//you will see undefined
console.log(func());


So, i hope you see my point. I don't like too much language flexibility because it helps and even encourages to create error-prone, inconsistent, and confusing code.

Friday, April 22, 2011

The best free software to convert pdf to mobi

Mobipocket creator ( http://www.mobipocket.com/en/DownloadSoft/default.asp?Language=EN ) is the best software i've seen so far that can convert a pdf file to mobi in very good quality. My opinion, it is much better than calibre ( http://calibre-ebook.com/ ), another ebook format conversion software.

Kindle fans know that kindle supports pdf poorly. I personally feel kindle supports .mobi as good as its own .azw. At least i haven't found any difference between them. They both bring me same comfortable reading experience.

Tuesday, April 12, 2011

start to learn extjs

i have to say i'm not very enjoying it. Maybe because it is not my comfort zone, i haven't get used to it yet. But i do like its philosophy - OPOA(One Page, One Application)

Thursday, March 31, 2011

javascript object oriented programming 3 - inheritance

inheritance - more details

Let's review the simple inheritance example in my last  blog:

//constructor method
function Person(name, sex) {
       this.name = name;
       this.sex = sex;
   }
//define Person prototype 
Person.prototype = {
       getName: function() {
           return this.name;
       },
       getSex: function() {
           return this.sex;
       }
}
//define an Employee constructor method
function Employee(name, sex, employeeID) {
    this.name = name;
    this.sex = sex;
    this.employeeID = employeeID;
}

Employee.prototype = new Person();
Employee.prototype.getEmployeeID = function() {
    return this.employeeID;
};
As we said, there are some problems in this inheritance. Let's address these problems one by one.
1. When we create the Employee constructor method and protoype, we also have to create a Person instance. It is not reasonable and not efficient.
To fix this issue, we should try to inherit the prototype only. We should put reusable properties and methods into prototype. Let's change our code:
Employee.prototype = Person.prototype;

In this way, every time we create a new Employee object, it can access any methods and properties in Person's prototype too. And we don't need to instance a Person object.

2. Another problem is Employee's prototype is completely re defined, this will cause Employee's constructor is referencing to the wrong object. Try the code below:


var e = new Employee('henry', 'm', 25);
console.log(e.constructor == Employee); //false
The constructor is not pointing to itself. To fix this issue, we simply change our code to this:
Employee.prototype = Person.prototype;
Employee.prototype.constructor = Employee.
3. Directly copying Person's prototype to Employee's prototype is easy and efficient. But it does bring some side effects. Employee's prototype is pointing to the same object, the Person's prototype, Employee's prototype properties and methods will complete override its parent object's prototype's same name properties and methods.
For example, if we also define a getName method in Employee's prototype:
Employee.prototype.getName = function(){return 'henry'};
var p = new Person('Jack', 'm');
p.getName(); //henry

To fix this issue, we must break the chain. We need to introduce an intermediary. We create an empty functoin F(){} first. Then we set its prototype to Person's prototype: F.prototype = Person.prototype. Now, let's see how we should do the inheritance:
function F(){};
F.prototype = Person.prototype;
Employee.prototype = new F();
Employee.prototype.constructor = Employee;

4. How to call parent object's method in child object? Javascript doesn't have someting like PHP's 'parent::' feature. There are several implementations for this. I just use a simple and traditional way: uber property. Finally the inheritance mechanism is:
var F = function() {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.uber = Parent.prototype;

What is the uber? Let's change our Person's getName method:
getName: function() {
var parentName = '';
if (this.constructor.uber) {
if (this.constructor.uber.getName) {
         parentName = this.getName();
}
   }
   return this.name + "'s parent is " + parentName;
}

Monday, March 28, 2011

javascript object oriented programming 2: inheritance

Inheritance - simple way

First, we need to know prototype. We can think prototype as a template. In javascript, everything is an object, every object has its own prototype.

A simple inheritance in javascript:
//constructor method
function Person(name, sex) {
       this.name = name;
       this.sex = sex;
   }
//define Person prototype 
Person.prototype = {
       getName: function() {
           return this.name;
       },
       getSex: function() {
           return this.sex;
       }
}
//define an Employee constructor method
function Employee(name, sex, employeeID) {
    this.name = name;
    this.sex = sex;
    this.employeeID = employeeID;
}
// Make Employee.prototype link to an instance of Person
// The Person instance can call the methods in Person prototype, so Employee's instances can access methods and properties of Person prototype as well.
Employee.prototype = new Person();
Employee.prototype.getEmployeeID = function() {
    return this.employeeID;
};
However, there are some problems with such a simple inheritance.
1. When we create the Employee constructor method and protoype, we also create a Person instance. That is not reasonable.
2. Employee's constructor method cannot access its parent/super class Person's constructor method.
3. Employee's constructor is pointing to the wrong place.
We will see how to address all these problems in my next blog.

Pass parameters to a function/expression called within setTimeout

javascript's setTimeout(aFunction,  timeout); Sometimes we need to pass parameters to aFunction. To do this, we must use 'closure': setTimeout(funciton(){aFunction(parameter)}, timeout);