This question already has an answer here:
I've seen How does "this" keyword work within a function?, but I don't see that it answers the following.
Given this code:
var MyDate = function(date) {
this.date = date;
};
var obj1 = {
foo: new Date(),
bar: new MyDate(this.foo) // this.foo is undefined
};
var obj2 = {};
obj2.foo = new Date();
obj2.bar = new MyDate(this.foo); // this.foo is undefined
var obj3 = {
foo: new Date(),
bar: new MyDate(obj3.foo)
};
var obj4 = {};
obj4.foo = new Date();
obj4.bar = new MyDate(obj4.foo);
Why do the first two attempts fail, but the last two work? If this
isn't bound to the current object literal, what is it bound to?
this.foo
is undefined because in all your examples,this
is referring to the globalwindow
object. Also, even if you triedobj1.foo
, it will still return undefined because the property hasn't been created until the entire expression is evaluated. Try this instead:It works because by the time you call
obj1.bar()
, the object will have been created by then; and because you're in a function, thethis
object will reference the current object.Javascript is a late binding language. In fact, it is very late binding. Not only is
this
not bound during compile time, it is not even bound during runtime (as most other late binding languages do). In javascript,this
is bound during call time.The binding rules are quite different from most other OO languages which is why it seems to confuse a lot of people not familiar with javascript.
Basically, how and where you use
this
in the code does not affect howthis
behaves (it does not matter if it's a standalone function, an object literal etc.) what determines the value ofthis
is how you call the function.The rules are:
1 - When a function is called as a constructor, a new object is created and
this
is bound to that object. For example:2 - When called as an object method
this
refers to the object the method belongs to. Basically the name before the last dot. For example:3 - If used outside of any function or if a function is not called as a method
this
refers to the global object. The javascript spec doesn't give a name to the global object apart from saying that one exists but for browsers it is traditionally calledwindow
. For example:4 - In an event handler (such as onclick etc.)
this
refers to the DOM element that triggered the event. Or for events not associated with the DOM likesetTimeout
orXMLHTTPRequest
,this
refers to the global object. For example:5 - Finally, when a function is called using either the
call()
orapply()
methodsthis
can be reassigned to anything whatsoever (google "mdn function.prototype.call"). In this way, any object in javascript can borrow/steal another objects' methods. For example:Update:
With
Function.bind()
in modern javascript implementations we now have another rule:6 - Functions can also explicitly bind
this
to an object using thebind()
method. Thebind
method returns a new instance of the function wherethis
is bound to the argument passed tobind
. For example:More update:
ECMAscript 5 introduced strict mode which changes the meaning of this in functions that isn't called as a method or called with call or apply so we have to add a new rule:
7 - When in strict mode,
this
isn't allowed to refer to the global object (window in browsers). So when a function is not called as a method orthis
isn't bound to anything manually viacall
orapply
orbind
thenthis
becomesundefined
:Even more update:
ECMAscript 6 introduced arrow functions. Arrow functions change how this behaves by binding early.
8 - In arrow functions,
this
is bound at the time the function is declared. Sothis
in the following code:behaves as if the function is declared like the following code:
Note that since the
this
in arrow functions are bound at the time the function is declared you can't use arrow functions if you want to use inheritance. That's because thethis
in the function will always point to the parent object and will never point to the child object. That means that the only way to make inheritance work with arrow function is to override all arrow functions from the parent object.In Javascript, only function calls establish a new
this
context. When you callfoo.bar()
, within thebar
function,this
will be bound tofoo
; when you callfoo()
, inside itthis
will be bound towindow
. An object literal constructor is not a method call, so it does not affectthis
in any way; it will still refer to whatever it was referring to outside of the object literal.I think you may be missing a key difference between functions and object literals:
The body of a function is not evaluated until the function is called.
The body of an object literal is evaluated right away.
When you define a function,
this
isn't bound to anything related to the function you're defining. But by the time the function is called, it is bound to the object on which the function was called as a method.