Technology

“this” in JavaScript: So many uses for a four letter word

Posted by Pixafy Team

"this" in JavaScript: So many uses for a four letter word  |  www.pixafy.com

One of the most confusing topics in JavaScript is the ‘this’ keyword. In high-level programming languages, such as Java, ‘this’ is referring to the current object instantiated by the class. In JavaScript ‘this’ normally refers to the object which owns the current method or function, but this depends on how the function is executed.

Every JS runtime has a global object; in a browser that global object is the window. The window object stores the information about the document, location, history and many other useful properties and methods. Consider the following example where I will add a property to the global object.

window.globalProperty = "I am the global object";
alert(window.globalProperty);  //I am the global object
alert(this.globalProperty);  // I am the global object
alert(window  === this); //true

I’ve attached my property globalProperty to the window and you can see by calling it using the window object or with ‘this’ that ‘this’ refers to the window object.

‘this’ remains in the global scope even if you’re calling it using a function.

window.globalProperty = "I am the global object";
function testScope() {
                alert(this.globalProperty);  //I am the global object
                alert(window === this); //true
}
testScope();

 

Using objects

However, for method functions, that is functions that are referenced using object properties the scope can change.

NewObject = {
                method: function(val) {
                                this.val = val;
                }
}
NewObject.method("hello");
alert(NewObject.val);//hello

The value of ‘this’ is bound to NewObject at invocation. In simpler terms, since NewObject is the receiver of the call to the method function call, the current scope is NewObject not the window.

Things get more unintuitive when using ‘this´ inside a nested function.

NewObject = {
                method: function(val) {
                                this.val = val;
                                var nested = function() {
                                                alert("The value was set to " + this.val);  // The value was set to undefined
                                }
                                nested();
                }
}
NewObject.method("hello");

The value of ‘this´ refers to the global object and is not bound to NewObject like its parent. This is because nested is invoked on a method and does not have a receiver like the example above (NewObject.method(“hello”);). This is true no matter how the function is scoped.  That is why you will often see code like this:

NewObject = {
                method: function(val) {
                                var self = this;                    
                             this.val = val;
                                var nested = function() {
                                                alert("The value was set to " + self.val);  // The value was set to hello
                                }
                                nested();
                }
}
NewObject.method("hello");

By assigning ‘this’ to a variable you can get around the default behavior.


Using the new operator

The new operator can override the default behavior of how ‘this’ is usually bound. When you invoke a function with new, you’re invoking it as a constructor function and creating a new object.

function testScope(val) {
this.val = val;
}
NewObject = new testScope("hello");
alert(NewObject.val); //hello


Using Call and Apply

The functions call and apply allow you to pass an argument for the object you wish ‘this’ to be bound to.

function testScope(val) {
this.val = val;
}
NewObject = {}
testScope.call(NewObject, "hello");
alert(NewObject.val); //hello

The only difference between call and apply is that apply allows you to invoke a function with arguments as an array, call requires you to list the parameters explicitly.

Do you have any questions or comments? Please leave us a message below or tweet us @Pixafy!