Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The scope of "this"

Tags:

javascript

I have a simple object and I don't understand the concept(scope) of this by calling the functions of this object.

Why in the last variant (3) calling show() (with the function show() inside object without parent) the result is "This is global" and not the inside variable title("Color Picker")?

I have the vague idea that calling the function popup.show() after the gloabal variable show is defined, this refers to the global object. Is this the logic explanation?

The code: http://jsbin.com/otuzac/1/edit.

var title="'This' is global";

var popup={
    dom_element:("#popup"),
    title      :"Color Picker",
    prev_color :'#fff',
    set_color  : function(color){
        color=color || this.prev_color;
        //set the color
        return color;
    },
    show       :function(){
        return("showing  "+this.title);
    }       
};

var show=popup.show();

//Case 1: var show=popup.show()
alert(show);  //output "Color Picker"

//Case 2: var show=popup.show()
alert(popup.show());  //output "Color Picker"

//Case 3: var show=popup.show !!! (no parent.)
alert(show());  //output "This is global"
like image 654
Alexis Avatar asked May 30 '13 09:05

Alexis


1 Answers

What this is depends on how you call the function in which you use this.

1. call as a function

functionName();

In this case this will always refer to the global object (most often the window object).

Example

a = 2;
function XY(a) {
    this.a = a;
    this.b = function () {
        func();
    };

    function func () {
        console.log(this.a);
    }
}

var xy = new XY(1);
xy.b(); //2

Remarks

  • The example is a little bit constructed, but note, that the function func is called by simply write func();. So even if your function is places inside a constructor function (XY) and called from a function that is called as a method (see point 3), this still refers to the global object.

2. call with new keyword

var obj = new functionName();

In this case this will refer to the new created object.

Example

a = 2;
function XY(a) {
    this.a = a;
}

var xy = new XY(1);
console.log(xy.a); //1

3. call as a method

obj.functionName();

In this case this will refer to the object that contains the function you are calling.

Example

a = 2;
var xy = {
    a: 1,
    func: function() {
        console.log(this.a);
    }
}
xy.func(); //1

4. call by using apply

functionName.apply(thisObj, argArray);

In this case this will be new Object(thisObj), with thisObj being the first argument of the function apply.

Example

function xy (a,b) {
    console.log(this);
}

xy.apply({f:3}, [1,2]); //Object {f: 3} 
xy.apply("hello", [1,2]); //String {0: "h", 1: "e", 2: "l", 3: "l", 4: "o"}

5. call by event handler

As the user Mifeet suggested, events also change the context of this:

Events are kind of a separate topic. They are not part of EcmaScript and are generally handled by different browsers differently. Nevertheless, the differences concerning this are minor and for IE > 8 as far as I know nonexistent.

this will refer to the DOM element that fired the event, except when you use inline event handler. In that case this will refer to the global object.

Example

<button id="1" onclick="clickit()">click me</button>  <!-- 0 -->
<button id="2">click me</button>
<button id="3">click me</button>
<script>
var button1 = document.getElementById("1");
var button2 = document.getElementById("2");
var button3 = document.getElementById("3");

id = "0";

window.clickit = function(){
    console.log(this.id);
};


button2.onclick = clickit; //2
button3.addEventListener("click", clickit, false); //3
</script>

Remarks to Events

  • Internet Explorer prior to version 9 didn't support addEventListener but attachEvent. Using this function will also result in this refering to the global object.
  • this, directly inside the HTML tag, will refer to the DOM element representing that tag. Therefore <button id="1" onclick="clickit(this)">click me</button> will pass the DOM element to the clickit event handler.

back to your case

In your first two cases, you are calling your function as a method and in the last case, you are calling it as a function. That is why in the last case, this refers to the global object.

EDIT

I recently saw a very similar answer to a very similar question here on StackOverflow. Unfortunately I couldn't find it anymore, so I decided to post an answer by myself. But if someone knows what answer I mean, just leave a comment and I'll be happy to put a link to the original answer in my answer.

like image 68
basilikum Avatar answered Nov 15 '22 12:11

basilikum