Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Object Oriented JavaScript - Understanding Scope

DZone's Guide to

Object Oriented JavaScript - Understanding Scope

· Web Dev Zone
Free Resource

Learn how to build modern digital experience apps with Crafter CMS. Download this eBook now. Brought to you in partnership with Crafter Software

When you think of the keyword this you probably assume it refers to the current instance of the class. This is true for most object oriented languages like C# and Java.

For example I could use the this keyword in C# like this:

class Cat {
string _name;
public Cat(string name) {
this._name = name;
}
}

In the above example you see this illustrated. In C# and Java, this always refers to the class instance.

So, knowing this you would probably assume the same would be true of JavaScript and it’s this keyword. This is, however, not the case. Like a lot of things about writing object oriented code in JavaScript, this behaves differently in some situations. this does not always refer to the class instance depending on how you use it.

function Cat(name) {
this.Name = name;
}

In the above example it works just like our C# example but let’s look at a situation where things can go wrong if you are unaware of some rules.

var wrong = new WrongClass();
wrong.publicMethod();

function WrongClass() {
this.publicProperty = 'props';
this.publicMethod = function() {
console.log('public method');
privateMethod();
};
var privateMethod = function() {
console.log('private method');
console.log('public property equals ' + this.publicProperty);
};
}

In my examples I am using the console object of Firebug to output my data.

So what is wrong with the above example? It looks like everything should work, right? Well, operating on the assumption that this always refers to class instance then the above code would be correct. We are, however, using JavaScript and shouldn’t be that surprised that it does things a little differently.

The output when publicMethod() is called would be:

>>> public method
>>> private method
>>> public property equals undefined

The reason this.publicProperty is undefined is because when entering the private method the scope of this changed. It no longer means the current instance of the class ‘WrongClass’ but it now means the current instance of the function ‘privateMethod’.

Another situation where the scope of this would change is when dealing with event handlers.

document.getElementById('button').onclick = function() {
alert(this.id);
}

In the above example this would refer to the instance of the document element ‘button’. There are many cases of scope change that you need to be aware of when dealing with object oriented techniques.

Back to our ‘WrongClass’ example. I’ll show you how to make that example work the way you would have expected it to work in the first place.

var right = new RightClass();
right.publicMethod();

function RightClass() {
var self = this;
this.publicProperty = 'props';
this.publicMethod = function() {
console.log('public method');
privateMethod();
};
var privateMethod = function() {
console.log('private method');
console.log('public property equals ' + self.publicProperty);
};
}

You’ll see that in the above code I have declared a variable called self. I assign this to this variable. This allows me to then use ’self’ any time I want to refer to the class instance without worrying about scope.

You can call your variable anything you like but ’self’ seems to be a common practice. So, now in ‘privateMethod’ when ‘publicProperty’ is called using ’self’ it will output the proper value.

>>> public method
>>> private method
>>> public property equals props
 

Crafter is a modern CMS platform for building modern websites and content-rich digital experiences. Download this eBook now. Brought to you in partnership with Crafter Software.

Topics:

Published at DZone with permission of Justin Bezanson. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}