在这段代码中,为什么foo和this.foo引用不同的东西?

时间:2015-06-18 05:08:58

标签: javascript closures

以下是代码:

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);
}

为什么ithis.i会引用不同的内容?

将此与在全局范围内执行的一些代码进行对比:

var x = 5;
console.log(x);
console.log(this.x);//both will print 5

这里的范围是全球性的,背景也是如此。变量声明在全局上下文中设置相同名称的属性。另一方面,在功能范围内,这不会发生。

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();

即使我们将全局上下文传递到本地范围,在函数中声明变量也不会将其设置为全局上下文的属性。

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

我想说的是:在全局范围中,变量声明会修改全局上下文。但是在功能范围中,无论上下文是什么,变量声明都不会修改函数的上下文。为什么呢?

2 个答案:

答案 0 :(得分:2)

当您将全局范围视为窗口时,它会有很大帮助。所以你可以在窗口的上下文中说全局运行。真的是这样:

var x = 5;
console.log(x);
console.log(this.x);//both will print 5

在最后一行,thiswindow,因此您正在运行console.log(window.x)

当您使用bind时,您更改了&#34; bound&#34;内的this的引用。功能。例如:

var x = 10;
function log() {
  console.log(this.x);
}

log(); // logs 10

log.bind({x: 20})()  // logs 20

bind调用使this内的log成为我们使用{x: 20}创建的匿名对象的引用。你也可以这样做:

var myObject = {x: 50};
log.bind(myObject)(); // logs 50

答案 1 :(得分:0)

考虑到这一点,这种行为是有道理的。感谢所有评论和回答的人。它帮助我思考了这件事。

  1. 从基础开始,在JavaScript中,变量的范围仅限于定义它的函数。
  2. 在全局范围内,var声明会将var设置为全局上下文的属性(精细)
  3. 如果我们想在函数范围内使用相同的行为,var声明将修改函数的上下文对象。但这有以下问题:

    一个。如果函数的上下文是某个对象,则函数中的每个var声明都将设置为对象的属性。所以这会发生:

  4. 函数具有对象上下文:

    //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
    

    湾如果未设置函数的上下文,则其上下文是全局对象。我们已经知道了。但是如果允许函数中的var声明以与全局作用域中的var声明相同的方式修改上下文,那么函数作用域将变得毫无意义

    功能具有全局背景:

    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
    

    这就是为什么var在函数中以及在函数外部工作的原因不同。