George Bush found many things confusing! |
In 'Javascript: The Good Parts', Javascript Guru Doug Crockford describes four different invocation patterns, the "this" parameter is initialised differently in all four patterns: the method invocation pattern, the function invocation patter, the constructor invocation pattern and the apply invocation pattern
The Method Invocation Pattern
When a function is property of an object in javascript it is a method. When the method is invoked, the 'this' refers to that object. For example, in the code below the property getName is an anonymous function. If the anonymous function wishes to refer to the name variable it uses the 'this' notation.
var myObject = { name: "Staveley", getName: function () { return this.name; } }; console.log(myObject.getName());// Staveley.
It is worth stressing the importance of 'this' in the example above. If it is not used, the name will be the global one.
name="GlobalName"; var myObject = { name: "Alex", getName: function () { return name; // refers to name in global namespace. } }; console.log(myObject.getName());// Outputs GlobalName not Alex.
The Function Invocation Pattern
When a function is defined not as a method but just as a function (i.e. there is no property defining it in an object), the keyword 'this' refers to the the global object.
var getNameFunction = function() { name: "Alex"; console.log(">>getNameFunction(),name=" + this.name); }; // Invoking getNameFuction() outputs: undefined. // Because, this is equal to the global object // which has no name property. getNameFunction();
When another object has a property which calls the getNameFunction, the 'this' inside the
getNameFunction refers to that other object.
var obama = { name: "obama" }; obama.getName = getNameFunction; obama.getName(); // outputs obama!
But, an inner function does not share the method's access to the object as its 'this' is bound to the wrong value.
obama.getFullName = function() { var outputName = function() { console.log("barack " + this.name); }; outputName(); } // Invoking getFullName() outputs barack undefined. Why? // Because the innerfunction's 'this' refers to the global variable. // The global variable has no name property. obama.getFullName();
The solution is to assign another variable to the value this. By convention this variable takes the name 'that'.
obama.getFullName = function () { var that = this; var outputName = function() { console.log("barack " + that.name); }; outputName(); }; obama.getFullName(); // outputs barak obama
Inner functions confused Obama! |
Objects can be easily defined using object literal syntax. However, sometimes when many objects of the same type need to be defined there is a need for consistency. There is also a need to avoid repetition. Two good reasons to use constructor functions!
var Car = function(colour, reg){ this.colour= colour; // this refers to the object being created. this.reg = reg; }; var myRedCar = new Car("Red", "00D901"); var myGreenCar = new Car("Green", "00D902"); var myBlueCar = new Car("Blue", "00D903"); // Now test those assignments worked. console.log(myRedCar.colour + ", " + myRedCar.reg); // outputs Red, 00D901 console.log(myGreenCar.colour + ", " + myGreenCar.reg); // outputs Green, 00D902 console.log(myBlueCar.colour + ", " + myBlueCar.reg); // outputs Blue, 00D903
Now suppose we want to add a method common to all 'Car' objects. We do:
Car.prototype.getColour = function() { console.log(">> getColour(), colour = " + this.colour); };
In this case, the 'this' refers to the object created with the new prefix
myRedCar.getColour(); // outputs Red myGreenCar.getColour(); // outputs Green myBlueCar.getColour(); // outputs Blue
The Apply Invocation Pattern
When Apply (or Call) is used we are allowed to choose the value of 'this'. To do this,
we simply specify it as an argument.
myRedCar.getColour.apply(myGreenCar); // outputs green myGreenCar.getColour.apply(myRedCar); // outputs red
References:
1. Brilliant tutorial on Javascript objects: http://helephant.com/2008/08/17/how-javascript-objects-work/
2. Douglas Crockford: http://javascript.crockford.com/javascript.html
No comments:
Post a Comment