Reputation: 3531
Here's the code:
for (var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i); //prints 9 10 times
console.log(this.i); //prints 0, 1, 2...9
}.bind({i:i}), i * 1000);
}
Why do i
and this.i
refer to different things?
Contrast this to a bit of code executed on the global scope:
var x = 5;
console.log(x);
console.log(this.x);//both will print 5
Here the scope was global, and so was the context. A variable declaration set a property of the same name on the global context. On the other hand, within a function scope, this doesn't happen.
var a = function() {
var x = 5;
console.log(x); //5
console.log(this.x); //undefined
console.log(i); //undefined
console.log(this.i); //10
}.bind({i: 10});
a();
Even if we pass the global context into the local scope, declaring a variable within the function doesn't set it as a property of the global context.
var a = function() {
var x = 5;
console.log(x); //5
console.log(this.x); //undefined
}.bind(window);
a();
console.log(x); //undefined
console.log(this.x); //undefined
What I'm trying to say is this: in the global scope, a variable declaration modifies the global context. But in a function scope, a variable declaration doesn't modify the function's context, no matter what the context is. Why?
Upvotes: 6
Views: 836
Reputation: 3531
Thinking about this a bit more, this behavior makes sense. Thanks to everyone who commented and answered. It helped me think through this thing a bit more.
If we wanted the same behavior in function scope, the var declaration would modify the function's context object. But this has the following problems:
a. If the context of a function is some object, every var declaration within the function would get set as a property on the object. So this would happen:
Function has object context:
//if var declarations inside functions modified context
//this doesn't happen in reality
var ctx = {b: 5};
var a = function() {
var c = 7;
this.b = 10;
}.bind(ctx);
a();
console.log(ctx.b); //10, as expected
console.log(ctx.c); //7, wtf? I never set this
b. If the context of the function isn't set, its context is the global object. We already know this. But if var declarations within functions were allowed to modify context in the same way that var declarations in global scope do, then functional scope would become meaningless
Function has global context:
function a() {
var b = 5;
this.c = 10; //this refers to window. it is this function's context
}
a();
console.log(b); //outputs 5 if function vars could modify context, which means functional scope is dead
console.log(c); //outputs 10, as expected
That's why var
works differently in a function and outside of it.
Upvotes: 0
Reputation: 14419
It helps a lot when you think of global scope being on window. So you can say global runs in the context of window. So really:
var x = 5;
console.log(x);
console.log(this.x);//both will print 5
In the last line, this
is window
so you are running console.log(window.x)
.
When you use bind
, you change the reference of this
inside of the "bound" function. For example:
var x = 10;
function log() {
console.log(this.x);
}
log(); // logs 10
log.bind({x: 20})() // logs 20
The bind
call has made this
within log
be a reference to the anonymous object we created with {x: 20}
. You could also do this:
var myObject = {x: 50};
log.bind(myObject)(); // logs 50
Upvotes: 2