this
and variable scope are separate concepts. Variable scope refers to which variables can be accessed from where within your application. Just because you wrote var foo
somewhere doesn't mean that you can access it from everywhere throughout your codebase. In Javascript each function
introduces a new scope, and scopes nest in a way that inner functions have access to the scope of outer functions, but not vice versa.
this
on the other hand is simply a "magic" reference to the "current" object. Maybe it's helpful to explain this idea in the context of other, classical languages first:
class Foo {
protected $bar;
public function baz() {
echo $this->bar;
}
}
In PHP the magic keyword $this
refers to the current object instance. Each time you call new Foo
, a new instance of this class is created. Every time you call $foo->baz()
, the same function is executed, though with $this
set to the appropriate object instance so each object instance can access its own data.
In Python this is actually a lot more explicit:
class Foo:
def baz(self):
print self.bar
Python does not have a magic keyword to refer to the current object instance. Instead, every method call on an object gets the current object passed explicitly as its first argument. This is typically named self
. If Python seems too alien to you, the above in PHP syntax would be:
class Foo {
public function baz($this) {
echo $this->bar;
}
}
Technically the functions in those classes do not really "belong" to any "class". They're just functions. You just need some way for those functions to be able to refer to a polymorphic object in order for them to be instance methods. Take for example:
function baz($obj) {
echo $obj->baz;
}
That's essentially exactly the same as what the class method does above, with the difference being that $obj
is explicitly injected instead of $this
being magically "there".
Javascript has the same thing, except that this
is available in every function (not just "class" functions) and that the object this
points to can be freely changed at runtime. this
is simply a magic keyword that points to an object, period.
function Foo() {
this.bar = null;
this.baz = function () {
console.log(this.bar);
}
}
When calling regular functions on objects like foo.baz()
, this
typically refers to foo
inside of baz()
; though it really doesn't have to:
foo.baz.apply(someOtherObj);
This takes the function foo.baz
and calls it while setting the this
keyword inside baz
to someOtherObj
. It freely re-associates the function with another object instance, if you will. But only because the only thing that "bound" the function to the object in the first place was the this
keyword anyway. The function will still simply do console.log(this.bar)
, whatever this.bar
refers to.
A more complete example:
function Foo() {
this.bar = 'baz';
}
Foo.prototype.speak = function () {
alert(this.bar);
};
var o = new Foo();
o.speak(); // alerts 'baz'
alert(o.bar); // also alerts 'baz'
var o2 = { bar : 42 };
o.speak.apply(o2); // alerts 42
As you can see, this
doesn't limit the scope of anything. What's happening here?
The Foo
constructor is called with new Foo()
. new
simply creates a new object and executes Foo()
with this
set to this new object. Basically:
var tmp = {}; // tmp does not *actually* exist,
// that's more or less what `new` does behind the scenes
Foo.apply(tmp);
The Foo
constructor assigns the bar
property of that new object.
tmp.bar = 'baz';
The new object is assigned to o
.
var o = tmp;
o.speak()
is a function bound to that object through its prototype
. Calling it as o.speak()
, this
inside speak()
refers to the o
object. Because that object has a property bar
, this works.
- Notice that it's also possible to do
alert(o.bar)
. The .bar
property was set on this
originally, then this
became o
. So o
has the property .bar
, which is a regular property of the object. It's not scope limited or anything.
- Next, we simply create another object
o2
, which also happens to have a bar
property. Then we call o.speak
, but we explicitly override the choice of what this
refers to using apply
. We simply do a switcheroo on what object the this
keyword refers to. Thereby the speak
function alerts the bar
property of the o2
object.
As you see (hopefully, I know this can be brain bending at first), this
is nothing more and nothing less than a reference to an object. That's all. It doesn't limit at all the scope of anything. function
s limit scopes, this
is just an arbitrary object. Anything you set on this
is not limited in scope; on the contrary, it's always publicly accessible from anywhere you have access to the object.
It's incredible how trivial it all is once you manage to wrap your head around it. this
refers to an object, it is simply Javascript's magic keyword to refer to an object. There are certain trivial rules which object it refers to at any given time, but all those can be bend and broken and reassigned. An object is simply a thing with properties. The properties can be functions. Only functions limit variable scope. That's pretty much all there is to it. Don't try to interpret anything else into this.