486-js-whats-this

What is ‘this’ in JavaScript?

By | | JavaScript & CSS

9

JavaScript is a great programming language. That would have been a controversial statement a few years ago, but developers have rediscovered its beauty and elegance. If you dislike JavaScript, it’s probably because:

  • You’ve encountered browser API differences or problems — which isn’t really JavaScript’s fault.
  • You’re comparing it to a class-based language such as C++, C# or Java — and JavaScript doesn’t behave in the way you expect.

One of the most confusing concepts is the ‘this’ keyword. In most languages, ‘this’ is a reference to the current object instantiated by the class. In JavaScript, ‘this’ normally refers to the object which ‘owns’ the method, but it depends on how a function is called.

Global Scope

If there’s no current object, ‘this’ refers to the global object. In a web browser, that’s ‘window’ — the top-level object which represents the document, location, history and a few other useful properties and methods.


window.WhoAmI = "I'm the window object";
alert(window.WhoAmI);
alert(this.WhoAmI); // I'm the window object
alert(window === this); // true

Calling a Function

‘this’ remains the global object if you’re calling a function:


window.WhoAmI = "I'm the window object";
function TestThis() {
	alert(this.WhoAmI); // I'm the window object
	alert(window === this); // true
}
TestThis();

Calling Object Methods

When calling an object constructor or any of its methods, ‘this’ refers to the instance of the object — much like any class-based language:


window.WhoAmI = "I'm the window object";
function Test() {
	this.WhoAmI = "I'm the Test object";
	this.Check1 = function() {
		alert(this.WhoAmI); // I'm the Test object
	};
}
Test.prototype.Check2 = function() {
	alert(this.WhoAmI); // I'm the Test object
};
var t = new Test();
t.Check1();
t.Check2();

Using Call or Apply

In essence, call and apply run JavaScript functions as if they were methods of another object. A simple example demonstrates it further:


function SetType(type) {
	this.WhoAmI = "I'm the "+type+" object";
}
var newObject = {};
SetType.call(newObject, "newObject");
alert(newObject.WhoAmI); // I'm the newObject object
var new2 = {};
SetType.apply(new2, ["new2"]);
alert(new2.WhoAmI); // I'm the new2 object

The only difference is that ‘call’ expects a discrete number of parameters while ‘apply’ can be passed an array of parameters.

That’s ‘this’ in a nutshell! However, there are several gotchas which may catch you out. We’ll discuss those in my next post…

Craig Buckler

Craig is a Director of OptimalWorks, a UK consultancy dedicated to building award-winning websites implementing standards, accessibility, SEO, and best-practice techniques.

More Posts - Website

{ 9 comments }

satya ...... July 28, 2011 at 5:54 am

It was very nice. But recently I got an issue with firefox8(nightly build). Below are files to show the problem

fiel1 : child.htm

Home Page

function callFunc(url)
{
sampleFunc();
this.sampleFunc();
}

file2: home.htm

Child Page

function x()
{
var windows = [];
}
x.prototype.sampleFunc = function(val)
{
alert(this.frameElement)
}
function loadFun(url)
{
var iframeElem = document.getElementById(“loadFrame”);
var iframeElemWindow = iframeElem.contentWindow;
for (var i in x.prototype) iframeElemWindow[i] = x.prototype[i];
iframeElemWindow.callFunc(“sampleURL”);
}

Steps to test:
1. make sure src of loadFrame in home.htm is child.htm
2. Open home.htm
3. two alerts will come
4. In all browsers except FF8-nightly build, I am getting both alert values loadFrame(HTML Element). But in FF8-nightly I m getting first alert as null and second alert value is loadFrame(HTML Element). “null is because”, “this” is referring to the window of the home.htm.

Note: Logged a bug to firefox previously. They fixed and reverted the patch with following comment,
“We fixed it, thanks again for filing it. We are now going to try breaking it again, in order to have simpler code and match the ECMA-262 Edition 5.1 spec extrapolated to work in the browser in the obvious way.”

My Problem is, I have to get the frameWindow of loadFrame in the first call also(first alert). How can I get this?? Even using callee or caller combination doesn’t helped me. Plz help to get rid of this probelm.

Thanks in advance

DN March 6, 2011 at 6:18 pm

very Nice work.

Juno March 5, 2011 at 3:16 am

yeah. I hate javascript’s this. Confusing. You can call me stupid hahah. Good writing.

CandleForex February 26, 2011 at 10:51 am

If a person is going to use javascript, they would be well advised to use GZIP compression and browser caching using .HTACCESS.

I have seen speed increases for everything (php, javascript and html etc…everything literally) of up to 70%.

Its very simple to do, just add the two variables into your .htaccess:

# BEGIN FORCE USE OF BROWSER CACHE
FileETag MTime Size

ExpiresActive on
ExpiresDefault “access plus 1 year”

#END FORCE USE OF BROWSER CACHE

# BEGIN, compress certain file types by extension:

SetOutputFilter DEFLATE

# END Or, compress certain file types by extension

Trent Reimer February 26, 2011 at 1:59 am

Good examples.

“‘this’ remains the global object if you’re calling a function”

Looking at it that way the behaviour appears consistent. A function is basically a method of the global object, isn’t it?

Craig Buckler February 27, 2011 at 9:29 pm

Thanks Trent — yes, that’s correct and a good way to remember it.

Bob February 25, 2011 at 11:43 pm

Okay, this article makes no sense to me at all. What exactly is “this” and why is it used at all? It seems to just be a substitute for a variable, but you cannot tell at all from this article, which seems to assume you know how “this” is used in other programming languages. Is “this” useful? Why use it when other methods of programming are much more clear? I’ve written thousands of line of workable and efficient code that is very easy to understand and follow without using “this” once.

Craig Buckler February 26, 2011 at 1:25 am

You’ve never used ‘this’ once? It’s essential if you’re doing any type of object-orientated programming in JavaScript (or any other language).

JS doesn’t force you to use OOP, but the concepts remain useful if you’re writing reusable code.

Peter Galiba February 25, 2011 at 5:19 am

And don’t forget about primitives that are the context of the functions, when called by `call` or `apply`. In that case the primitives like boolean, number and string are converted to the Object counterpart of the primitive value.
Just look at the following script:

var values = [0, true, "string", NaN, undefined, null], i = 0, l = values.length, value;
function typer() { console.log(‘INSIDE: value: ‘, this.toString(), ‘, type: ‘, typeof this); }
while (i < l) {
value = values[i++];
console.log('OUTSIDE: value: ', value, ', type: ', typeof value);
typer.call(value);
}

The following output is written to console:

OUTSIDE: value: 0 , type: number
INSIDE: value: 0 , type: object
OUTSIDE: value: true , type: boolean
INSIDE: value: true , type: object
OUTSIDE: value: string , type: string
INSIDE: value: string , type: object
OUTSIDE: value: NaN , type: number
INSIDE: value: NaN , type: object
OUTSIDE: value: undefined , type: undefined
INSIDE: value: [object Window] , type: object
OUTSIDE: value: null , type: object
INSIDE: value: [object Window] , type: object

So the null and undefined values when used as `this` will be converted to the global object.

Also don't forget about strict mode, which changes the meaning of this. When calling a function, the `this` will not be converted into the global object, not even with null or undefined set as the `this` in case of `call` or `apply`. In that case `this` will be null or undefined.

Comments on this entry are closed.