What's this?



In JavaScript, a function is an object, an instance of Function. You can assign it to a variables or parameter. Of course, it's also workable to assign functions to the object properties. For example:
js> var p1 = { name : 'Justin', age  : 35 };
js> var p2 = { name : 'momor', age  : 32 };
js> function toString() {
  >     return '[' + this.name + ',' + this.age + ']';
  > }
js> p1.toString = toString;

function toString() {
    return "[" + this.name + "," + this.age + "]";
}

js> p2.toString = toString;
function toString() {
    return "[" + this.name + "," + this.age + "]";
}

js> p1.toString();
[Justin,35]
js> p2.toString();
[momor,32]
js>

In the above example, a toString function is declared and then assigned as the toString properties of p1 and p2. When p1.toString() is executed, toString is like the method of p1. When p2.toString() is executed, toString is like the method of p2.

The function toString uses the this keyword. Every function has a this object. The this object represents the current object. It depends how to call a function. For the above example, when p1.toString() is executed, this is the object referred by p1 so the returned string contains values of p1.name and p1.age. If p2.toString() is executed, this is the object referred by p2.

If you call a function through an object,  this is the "owner" of the function. For example, when obj.func() is executed, obj is the owner of func and the reference of func and this is the same.

In JavaScript, a function is an instance of Function. All Function instances have a call method. The first parameter lets you decide what object this will be. For example, you can call a function as follows:
js> var p1 = { name : 'Justin', age  : 35 };
js> var p2 = { name : 'momor', age  : 32 };
js> function toString() {
  >     return '[' + this.name + ',' + this.age + ']';
  > }
js> toString.call(p1);
[Justin,35]
js> toString.call(p2);
[momor,32]
js>


This time, the function toString is not an object property. The example uses a call method to call toString. The first parameter accepts the object which this will be in the function. If a function accepts arguments, you can append them after the first argument of the call method. For example:
js> function add(num1, num2) {
  >     return this.num + num1 + num2;
  > }
js> var o = { num : 10 };
js> add.call(o, 20, 30);
60
js>


All Function instances also have an apply method. It's similar to the call method. The first parameter of apply accepts what this will be. You have to use an array to collect arguments when calling apply if you want to specify arguments of the applied function. Use apply if you have a list of reusable arguments among several functions. For example:
js> function add(num1, num2) {
  >     return this.num + num1 + num2;
  > }
js> var o1 = { num : 10 };
js> var o2 = { num : 100 };
js> var args = [20, 30];
js> add.apply(o1, args);
60
js> add.apply(o2, args);
150
js>


So, what this will be depends on how to call a function but not what object a function is belonging to. You can let this refer to another object even if a function is a property of an object.
js> var p1 = { name : 'Justin' };
js> var p2 = { name : 'momor' };
js> function toString() {
  >     return this.name;
  > }
js> p1.toString = toString;
function toString() {
    return this.name;
}

js> p2.toString = toString;
function toString() {
    return this.name;
}

js> p1.toString();
Justin
js> p2.toString();
momor
js> p1.toString.call(p2);
momor
js>


The last statement is p1.toString.call(p2). Although toString is a property of p1, but the first argument of call specify p2 for this so it returns the value of p2.name.

If you use an object literal to create an object, the values of properties can also functions. For example:
js> var o = {
  >     name : 'Justin',
  >     toString : function() {
  >         return this.name;
  >     }
  > };
js> o.toString();
Justin
js>


The top-level functions are properties of the global object. If you call a top-level function, this is the global object. For example:
js> function func() {
  >     return this;
  > }
js> func() == this;
true
js> this.func() == this;
true
js>


When you can a local function directly, such as function_name(), this also refers to the global object. For example:
js> function func() {
  >     function inner() {
  >         return this;
  >     }
  >     return inner();
  > }
js> func() == this;
true
js> var o1 = { func : func };
js> o1.func() == o1;
false
js> o1.func() == this;
true
js> func.call(o1) == this;
true
js>


Even if func uses the call method and specifies o1 for this of func, this of the inner function still refers to the global object when called. You can compare the above example with the following example:
js> function func() {
  >     function inner() {
  >         return this;
  >     }
  >     this.inner = inner;
  >     return this.inner();
  > }
js> func() == this;
true
js> var o1 = { func : func };
js> o1.func() == o1;
true
js> o1.func.call(this) == this;
true
js> o1.func.call(o1) == o1;
true
js>


It's important to figure out what this will be when a function is called. It depends on how to call a function, not how to define a function.

For example, if you want to implement your own forEach method, as follows:   
js> var obj = {
  >     '0' : 100,
  >     '1' : 200,
  >     '2' : 300,
  >     length : 3,
  >     forEach : function(callback) {
  >         for(var i = 0; i < this.length; i++) {
  >             callback(this[i]);
  >         }
  >     }
  > };
js> obj.forEach(function(element) {
  >     print(element);
  > });
100
200
300
js>


In the above example, when obj.forEach(...) is executed, obj and this will have the same reference so you can use properties of obj, such as length. A function is an object so you can pass it to forEach. The above example is the basic demonstration about how to implement the forEach method of Array. The forEach method has been introduced in Array.