Tuesday, May 10, 2011

copy arrays & objects in javascript

In javascript, when we assign an array or object to a variable, we are actually making a reference to the objects(array is object too). check this code:

var a = ['henry'];
//b is a reference to a
var b = a;
b[0]   = ['li'];
//we can see a[0] is changed to 'li' as well
console.log(a[0]);



In some situations, however, we may just want a copy of the object, instead of a reference.

Let's see how to deal with array first. Copying an array in javascript is surprisingly easy, thanks to the array.slice(start, end) method. The slice() method selects a part of an array, and returns the new array. It accepts two parameters: start, end. If we set start to 0, and omit the end, the method will actually return a copy of the whole array. Check this code snippet:

var a = ['henry'];
//b is a copy of a
var b = a.slice(0);
b[0]   = ['li'];
//we can see a[0] is still 'henry'
console.log(a[0]);


When it comes to an object, things are not that easy. javascript doesn't have any method for us to copy an object(one of the things i can't believe).  Fortunately, we can create a prototype method to achieve this goal.

//first, we must know that all javascript objects(function, array, custom objects) are instances of Object.
//and we just create an Object prototype clone method  
Object.prototype.clone = function() {
  //first, it check if this is an array or object
  var cloneObject = (this instanceof Array) ? [] : {};
 //now look through the object's all properties
  for (i in this) {
    //if it is clone, then contiune
    if (i == 'clone') {
        continue;
    }
    //if the property is also a type of object, recursively call the clone method
    if (this[i] && typeof this[i] == "object") {
        cloneObject[i] = this[i].clone();
    } else {
        //if it is not object type, simply copy it
        cloneObject [i] = this[i]
    }
  }
  return cloneObject;
};




It is done! Now all javascript objects will have this clone method. Let's see how to use it:



//we create a constructor function

var Person = function (){
    this.name = 'henry';
    this.getName = function(){
        return this.name;
    }
}
//get a person object
var one = new Person();
//clone this object to two
var two = one.clone();
//now let's change two's name
two.name = 'henry li';
//we can see one's name remain unchanged.
console.log(one.getName());
console.log(two.getName());


Saturday, May 7, 2011

javascript object oriented programming 5 - private members 2(object literal)

My last blog shows how to achieve privacy for objects using function constructors. How about object literals?

Check the code:

//this is the object
var newCar;

//now, let js's anonymous immediate function do the trick
(function() {
//private members
var model = 'mazda 3';

//public implementation
//don't put 'var' before the newCar!
newCar = {
     getModel : function(){return model;}
};
}());

//now, let's call the getModel method, 
//you will get 'mazda 3'
newCar.getModel();


The way it works is easy to understand as long as we know, javascript object and function can provide local scope. So we just need a function to wrap the private data. In object literals, we can use the closure created by an additional anonymous immediate function.

But do we really want to create object privacy in this way? For me, this kind of code cannot be counted elegant. My last blog suggests we can simply use naming convention to achieve object privacy. It sounds not professional, but i believe that is the easiest way: easy to implement, easy to read, easy to understand, easy to modify.

Let's accept this truth: javascript is NOT especially designed as an object oriented programming language, it is  NOT  especially designed for OOP, even though it provides with the power/magic/flexibility that you can make it an OOP language or achieve all OOP language features.

I still believe the best word to describe javascript is plasticine. You can shape it and make it look like different things.

I have to declare that I am not against using javascript to do OOP. Actually, i believe we should apply OOA/OOP to any complicated and large javascript project, a web game, for example. But i don't think it is necessary that we twist javascript to prove that it is a fully OOP language.

Thursday, May 5, 2011

javascript object oriented programming 4 - private members

Let's check the code:
Car = {
   model : 'mazda 3',
   getModel : function() {return this.model},
}
//we can access the model property directly
console.log(Car.model);
//how about we use function constructor?
var Car = function() {
    this.model = 'mazda 3';
}
var newCar = new Car;
//we still can access the model property directly.
console.log(newCar.model);


In the above examples, we can't hide object's properties from being exposed. What if we want to have private properties and private methods/functions that can be accessed only in the object, just like what we do in java and php 5?

Same as we use object scope to achieve namespace, we can also create private members for our object.
var Car = function() {
    //the model variable is only visible within the Car object now!
   //so it becomes a private property of Car
    var model = 'mazda 3';
    //since function, which is object in js, can be assigned to a variable,
    //we can have private function too!
   // this upgrade function is only visible in Car scope!
    var upgrade = function(newModel) {
        model = newModel;
    };
    //a public method.
    this.getModel = function() {
        upgrade('mazda 6');
        return model;
    }
}
var newCar = new Car();
//will get undefined
console.log(newCar.model);
//will get error
newCar.upgrade('toyota');
//will get mazda 6
newCar.getModel();


Some people say javascript is a functional programming language, some argue it is object based language because almost everything is object in javascript, while others prove that javascript can have full OOP features just like other modern object oriented programming languages like java. 

I would say, javascript is a plasticine programming language! You can shape it as whatever you want !

Actually, i think we don't even need to bother about implementing those private member stuff. If we really want to have private, we can simply use naming convention: private members must be prefixed with underscore, for example:
var Car = function() {
    this._model = '3';
    this._upgrade = function(newModel) {
        this._model = newModel;
    };
    this.getModel = function() {
        this._upgrade('mazda 6');
        return this._model;
    }
}

And then, just tell your team members to follow this coding convention: when you see something prefixed with _, you know you shall not directly access it or change its status.

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)