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"
What this
is depends on how you call the function in which you use this
.
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
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.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
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
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"}
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
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.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With