Common mistakes using the “this” in javascript: understanding context

Coming from a classic object orientated programming background and then code in javascript could be some kind of confusing, because we try to apply the same concepts to this language when we try to use the this keyword. The thing is that Java and JavaScript are two very different languages, even if they have similar syntax. Let’s explain how it works:

In Java, we use the this keyword to make reference to the actual instance of the object we are working on.


public class  Employee {
       private String name;
       public void setName (String strName) {
                this.name = strName;
       }
}

Here the scope of this is at level class, always. That’s why we can omit in the code.


public class  Employee {
       private String name;
       public void setName (String strName) {
                name = strName;
       }
}

Employee  employee = new Employee();
employee.setName (“Joost Smith”);   // everything ok. 



In Javascript, the use of this keyword have a different meaning: is used to make reference to the actual context ( or object ) who is calling the function.
Let’s explain with some common mistake when started to code in javascript, in a intent to mimic the OO standard programming:


function Employee () {
         var name;
         function  setName  (name)  {
                    this.name = name;
        }
}

var   employee = new Employee ( );  

// *** we will get an  error !! employee.setName is not a function
employee.setName (“Joost Smith”);   


The problem here is the this keyword is making a reference to the actual instance like in Java code, but not the setName method. Why? Because the setName is defined as a function in the inner context of the employee instance but don’t belongs to it; is only accessible to all code in the Employee ( ) function and outside of that context doesn’t exists. This applies to the variable name too.

This is how we have to redefine the code so we can work with it:

function Employee ()  {
         this.name = “” ;  //  “instance variable” creation  
         this.setName  = function  (name)  {
                    this.name = name;
        }
}


In this code we are making explicit that the name variable and the setName method belongs to an object context.
As conclusion, in JavaScript is necessary to make explicit ( but not mandatory ) the context using the this keyword, otherwise we can fall in confusion: also because the functions in JavaScript represents a way for create a context of execution:

function modifyName( name )  {
         function addSuffix () {
                name =  “Mr.” +  name;  
         } 
    return  addSuffix();
}

alert (  modifyName (“Joost Smith”)  );   //  we get  “ Mr. Joost Smith “
In Javascript Context is interchangeable
What does it means ? It means that we can reassign a javascript function so it can works in the specific context of other objects:

 function getColor ( ) {    
   alert ( this.style.backgroundColor )   
};
 
var redDiv = document.getElementById("red") ;
redDiv.onclick = getColor; 

var blueDiv = document.getElementById("blue") ; 
blueDiv.onclick = getColor;



<div id="red" style="background-color: red"  />
<div id="blue" style="background-color: blue" />


Keeping a reference to initial context
Another common mistake I’ve found is when we want to manage the a javascript function as event handler:

function MyObject ()  {
        this.innerObject = new InnerObject ( );
        this.execute = function ( )  { 
                this.innerObject.execute()    
       }
}

var myObject = newMyObject(); 
otherObject.onclick = myObject.execute; 

And when we click on otherObject or execute otherObject.onclick () we get
TypeError: this.innerObject is undefined

Why we get this ? As I mentioned, the context is interchangeable. What we did here, is to change the context of the execute function: we are assigning to a function variable named onclick the execute function, and now this is making reference to the otherObject instance where the inner member innerObject doesn’t exists. To fix this we redefine the handler:

otherObject.onclick = function ()  {
      myObject.execute( );
}
Now we are executing the method in its original context.
Here we have another example:


function  changeLanguage()  {
      var hiddenLangField = document.getElementById(“lang”);
      hiddenLangField.value = this.id;
     // ...  form.submit code
}

function createLanguageLink (locale)  {
       var   changeLangLink  = document.createElement(“a”); 
       changeLangLink.id = locale; 
       changeLangLink.onclick  =   changeLanguage;
      document.body.appendChild (changeLangLink  );
}; 

// Initializing code 
for (var i = 0;  i < langs.length; i++) {
       createLanguageLink (langs[i]);
}


What’s wrong with this code ? Well, actually it will work. But these are some issues:
- We are relying in some global functions, that’s mean lack of encapsulation.
- This code it depends of the html id of the link.
- We are mixing html with some functional code with html user interface.

Let’s put some order:

function  changeLanguage(locale)  {
      var hiddenLangField = document.getElementById(“lang”);
      hiddenLangField.value = locale ;
     // ...  form.submit code
}

function createLanguageLink (locale)  {
       
       var   changeLangLink  = document.createElement(“a”); 
       changeLangLink.onclick  =   function () {
                     changeLanguage(locale);
       };
      document.body.appendChild (changeLangLink  );
}; 

// Initializing code 
for (var i = 0;  i < langs.length; i++) {
       createLanguageLink (langs[i]);
}
Here we are achieving to remove the dependency of the “id” link.
Or even better, we can avoid to create the html links in the Javascript code:

<a href =”#”  onclick= “changeLanguage (‘es’)  >Español </a>
<a href =”#”  onclick= “changeLanguage (‘fr’)  >Français </a>
<a href =”#”  onclick= “changeLanguage (‘en’)  >English </a>