Feb 23, 2008

Javascript notes

Object Creation

When a function used with new, it became a constructor

            function Dog()
            {
            this.name = "Fred";
            this.Bark = function()
            {
            alert("my name is " + this.name);
            };
            }

            var d = new Dog();
            d.Bark();
            

A constructor is a function that construct and return a object, to achieve this result it is not necessary to use new with a function. A little bit of change the function can do that

            function Dog()
            {
            this.name = "Fred";
            this.Bark = function()
            {
            alert("my name is " + this.name);
            };
            //you don't need this, if you don't want to call "var d = Dog()",
            //you can only use "var d = new Dog()"
            //if you want to support both, you need this
            return this;
            }

            var d = Dog()
            // var d = new Dog(); is still supported

            d.Bark();
            
Essentially, no matter whether you use "new" or not the function do the following
            function Dog()
            {
            var d = new Object();
            //or
            // var d = {}
            d.name = "Fred";
            d.Bark = function()
            {
            alert("my name is " + this.name);
            };
            return d;
            }
            var d = Dog()
            // var d = new Dog(); is still supported

            d.Bark();
            

Constructor/Prototype

In javascript, everything is object. event the constructor itself is an object. The instance created the constructor, is also an object. So that is relationship between two. Constructor function is an object, it has a member object with name called "prototype". This member object is a reference to an object, let's call it prototype object. The prototype object has definition of reusable behavior, it has member called "constructor", which reference to constructor. The instance object created by constructor is a different object, it has optional definition of new behavior. And it also has secret link to the prototype object that I just mentioned.

            alert(Dog.constructor); //function Function () { [native code] }
            alert(Dog.prototype); //[object Object]
            alert(Dog.prototype.constructor); //function Dog() {..}
            

prototype inheritance

What is inheritance? It is word to describe an effect, or you can say it is an effect, that is code reuse. In traditional language, this is achieved by classical inheritance. Using new class, we can create new object and its behavior. But in JavaScript, there is no class, every thing is object. But no matter whether it is traditional language, or javascript, object does the job, so creating object is common goal. So how, it turns out that we create new object based on old object, the old object is the prototype of a new object.

            function Dog()
            {
            this.name = "fred";
            return this;
            }
            function BigDog(){}
            BigDog.prototype = new Dog();
            var bd = new BigDog();
            alert(bd.name);

            
The above code to implement the reuse is not elegant, because there is not built-in construct to facilitate this process. It is quite ironic that it is prototype style language, but does not have build-in prototype construct. Douglas Crockford create the following function to support that.
            function object(o)
            {
            function F(){}
            F.prototype = o;
            return new F();
            }

            var bd = object(new Dog());
            alert(bd.name);
            

prototype inheritance style. using prototype keyword vs using closure

There is not classical inheritance in javascript, Douglas Crockford call "using prototype" is like Pseudoclassical Inheritance. Below is style of using prototype keyword

            function Gizmo(id) {
            this.id = id;
            }
            Gizmo.prototype.toString = function () {
            return "gizmo " + this.id;
            };

            function Hoozit(id) {
            this.id = id;
            }
            Hoozit.prototype = new Gizmo();
            Hoozit.prototype.test = function (id) {
            return this.id === id;
            };

            

Below is using the closure

            function symbol(s, p) {
            return {
            id: s,
            lbp: p,
            value: s
            };
            }

            function delim(s) {
            return symbol(s, 0);
            }

            function stmt(s, f) {
            var x = delim(s);
            x.identifier = true;
            x.reserved = true;
            x.fud = f;
            return x;
            }

            function blockstmt(s, f) {
            var x = stmt(s, f);
            x.block = true;
            return x;
            }

            

Generally, closure is more elegant, but is not very straight forward for javascript beginner. In the example above, all the inheritance is achieved by decorating an object in different constructor, since the constructor is in a stack. When top constructor is called, a object is returned from the bottom constructor, and object is modified in each constructor on the way to the top constructor.

Sigleton or static method

The idea is that we want to create an object with method, but we want there is only one instance of the object

            function Dog()
            {
            return {
            name:"fred",
            bark:function()
            {
            alert(this.name);
            }
            }
            }

            var d = new Dog();
            d.bark();

            var dog = function()
            {
            return {
            name:"fred",
            bark:function()
            {
            alert(this.name);
            }
            }
            }();

            dog.bark();

            

object, Function, function

Again in javascript, everything is object. var b = Boolean(), b is an object. Boolean is an object. var o = new Object(), o is an object, Object is an object. I think there are two kind of Object. One has property of prototype, and one that has not, but it can access propotype by obj.constructor.prototype. All object has constructor. Built-in objects such Array, Boolean, Date, Math, Number, Object, RegExp, String they are have prototype. They all have prototype member. Because they have prototype, they can use "new" keyword to create another kind of object, which does have prototype. functions also have property type, they can be used with new as constructor to create other normal objects which have no prototype member. To create function we can use "function" keyword.

            Function.prototype.method = function(name, func) {
            this.prototype[name] = func;
            return this;
            };

            function User(){}
            //this is actually var User = function User() {}
            //this is actually var User = new Function() {}

            alert(typeof Function); //function
            alert(typeof User); //function
            alert(typeof Function.constructor); //function
            alert(typeof User.constructor); //function
            alert(Function.constructor); //function Function(){ [native code] }
            alert(User.constructor); //function Function(){ [native code] }

            alert(User.method == Function.prototype.method); //true
            alert(User.prototype); //[object Object]
            alert(Function.prototype); //in IE it shows function prototype{[native code]}, in firefox it shows function(){}

            User.method("sayhi", function() { alert("hi"); });
            var u = new User();
            u.sayhi(); //alert("hi")

            

The interesting thing is that User.method == Function.prototype.method . Actually, then User is defined, a object let'say temp = new Function() is created, temp has a secret link to the Function.prototype, and the temp object is return. When you call User.method is actually calling temp.method. In our case, the method add member to temp object. When you call var u = new User();, the temp is return. So in essence The temp object has not definition of "method", so it will escalate the call to the Function.prototype object. Please know User.prototype is not equal to Function or Function.prototype. It is always [object Object]. Please note that in Function.prototype.method definition, there is statement, "returns this". This is not necessary, but is necessary for a cascade-style of programming, which is like obj.method1.method2.method3 instead of "obj.method1(); obj.method2(); obj.method3(); Douglas Crockford said, "When I write a method that doesn't need to return a value, I usually have it return this."