Tuesday, July 26, 2011

javascript 'this' keyword

Let's remember this rule: by default, javascript's 'this' always refers to the owner of the function or the object that has the function as a member. With this rule in mind, let's take a closer look at 'this'.

1. 'this' in a global function

var name = 'henry';
function sayHello() {
                console.log('hello ' + this.name);
}
sayHello();

In this example, what does 'this' refer to? Based on the rule, let's ask this question: what/who is the owner of sayHello() function? The answer is window (assuming in a browser environment). So 'this' refers to window. In fact, every so called 'global' stuff in javascript are members of the window object. So, the example will simply log 'hello henry'. And we probably know that in the sayHello() we can simply do console.log('hello ' + name);

2. 'this' in an event handler function

<html>
<head>
<script>
function alertName() {
    alert(this.value);
}
window.onload = function(){
    document.getElementById('name').onclick = alertName;
}
</script>
</head>
<body>
<input id="name" type="text"  name="name" value="my name is henry" />
</body>
</html>

Guess what? the code works perfectly fine. Back to the rule: 'this' always refers to function owner. In this case, the owner of alertName() is window. So the alert(this.value) should show 'undefined', right? But it does show the value in the input field. Let's dig this deeper. In javascript, everything is object. Function is object too and can be assigned as a variable. document.getElementById('name') returns a DOM object with id = 'name'. if we break document.getElementById('name').onclick = alertName into two steps, they are:

var domObj = document.getElementById('name');
domObj.onclick = alertName;

So what we do is actually assign(copy) alertName as a variable to domObj's onclick property. When we click the input field, domObj.onclick is triggered. Who is the owner of onclick? The answer is domObj, so 'this' is actually referring to domObj. To be more clear, we can alert(domObj.onclick); and the output is below:

function alertName() {
  alert(this.value);
}

Ok, so far so good. But let's change the above example to below:

<html>
<head>
<script>
function alertName() {
    alert(this.value);
}
</script>
</head>
<body>
<input id="name" type="text"  name="name" value="my name is henry" onclick="alertName()"/>
</body>
</html>

This time, it doesn't work. What is happening now? Let's alert(document.getElementById('name').onclick); and we see the output:

function onclick() {
     alertName();
}

See the difference? Now onclick is actually a function that invokes alertName(). So in this case, 'this' inside alertName is pointing to the window object.

We can actually change what 'this' refers to if we want. One example is to use 'apply' or 'call'. See http://hengrui-li.blogspot.com/2011/05/javascript-callback-function-scope.html

No comments: