Dec 7, 2010

"this" in javascript

If you don't know javascript is a functional language and you do lots of object oriented programming, the follow code must be very confusing for you.

var name = "Jerry";

var x = { name : "Tom",
          sayName1 : function () {
              alert(this.name);
           },
          sayName2 : function () {
             sayName3();
           },
           sayName4 : function () {
            sayName3.call(this); 
          }
        };

var sayName3 = x.sayName1;  

x.sayName1(); //show Tom //line a
sayName3();   //show Tom? no, it is Jerry //line b 
x.sayName2(); //show Tom? no, it is still Jerry!! //line c
x.sayName4();  //now it is Tom //line d

In OO language like C#, java, instance method belongs to an instance(object). The method knows "this" is referring the instance it belongs to. So if you use this concept to apply to javascript, you will think the behavior line a make sense. Line b will be confusing, and line c and line d is even confusing. In javascript, object can reference function, however functions don't belong to any object, and a function does not know what "this" is, until is called in one of the following case. Let's read the follow code


var x = new ConstructorFunction();
var y = simpleCallFunction();
var z = o.memberCallFunction();
var a = usingapplyCallFunction.apply(o, [p1, p2]);
var b = usingcallCallFunction.call(o, p1, p2);

In line y, the "this" in simpleCallFunction always refer to global object. In line a,b, they are basically the same,except the syntax, which specify the object that "this" is referred to. In line z, we can rationalize at as " var temp = o.membershipCallFunction; temp.call(o); " or just "o.membershipCallFunction.call(o);". Line x is constructor call, the "this" is the object being created.


What the global object is depends on the engine. In browser, it refers the window object. But there are other environment too. Here is how window object is passed in? When a page is loading, javascript engine convert the string in <script /> block to a function, let's say, x, then call x.call(window). That is why all your code in the block knows that "this" is window. In line y, you can rationalize it as " simpleCallFunction.call(window) ". The only special case is line x, which use function as a constructor. So what happens to native javascript object, for example, array. If you want to use push method of an array for a non array method, can you? Yes, you can, in fact, that is why jQuery object works like an array even though it is not an array. Here is trick.


var fQuery = { push: [].push }
fQuery.push("item1");
//it works like an array!!
//push method does not belong to array, you can apply it to any object
alert(fQuery [0]);
alert(fQuery.length);

In conclusion, javascript function does not belong to any object, "this" is parameter passed in implicitly or explicitly during the function is called, "this" is just the same as other parameter. However, the language just provide some misleading syntax (but it is also good syntax) to pass the parameter into a function.