5

我正在阅读一些关于 javascript 的文档,并偶然发现了以下代码示例:

var o = {
  value: 1,
  outer: function () {
    var inner = function () {
      console.log(this);  //bound to global object
    };
    inner();
  }
};
o.outer();

它输出window.

我无法弄清楚为什么关键字绑定到this全局对象 ( window) 而不是父对象 ( outer)。
如果outer要从inner' 范围内访问,则必须将outer' this(就像传递outer自身)inner作为参数传递给其本地函数。所以,正如预期的那样:

var o = {
  value: 1,
  outer: function () {
    var inner = function (that) {
      console.log(that);  //bound to global object
    };
    inner(this);
  }
};
o.outer();

输出outer

outer' 范围内绑定到对象this本身(即捆绑)?outerinnerouterthisouter


ECMAScript 规范指出,当进入函数代码的执行上下文时,如果 «caller provided thisArg» 为nullundefined this绑定到全局对象。

但以下内容:

var o = {
    outer: function () {
        var inner = function () {
            console.log('caller is ' + arguments.callee.caller);
        };
        inner();
    }
}

输出对象outer本身:

caller is function () {
    var inner = function () {
        console.log('caller is ' + arguments.callee.caller);
    };
    inner();
}



另一方面,但可能相关,请注意:
严格模式下,第一个代码段输出undefined而不是 window。

4

2 回答 2

6

这是因为this在函数运行时设置,而不是在定义时设置。

例如:

var o = {
    func: function(){
        console.log(this);
    }
};

当您调用时o.func(),您是在 context 中这样做的o,因此它按预期工作。

现在假设你这样做:

var f = o.func;
f();

这不会按预期工作。这是因为当您调用 时f(),它没有附加任何上下文,this所以window.

您可以通过使用.call更改 的值来解决此问题this

var f = o.func;
f.call(o);  // sets `this` to `o` when calling it
于 2013-06-12T19:52:22.023 回答
3

这就是语言的工作方式。

每次调用函数时,this都会重置。在嵌套(内部)函数中,它不会像其他(显式声明的)变量那样从封闭范围继承值。

默认情况下 this将设置为window除非该函数被调用为:

  • myObj.func(arg1, ...)或者
  • func.call(myObj, arg1, ...)或者
  • func.apply(myObj, [arg1, ...])

在这种情况下this将等于myObj

以任何其他方式调用的函数,即使它最初被定义为对象的属性(var func = myObj.func; func()即将使用window.

还有一个名为的实用函数.bind,它以这样一种方式包装函数引用,您可以提供一个特定的值,该值将始终用作this

var myFunc = myObj.func;                // obtain reference to func
var bound = myFunc.bind(someOtherObj);  // bind it to "someOtherObj"

bound();                               // this === someOtherObj
bound.call(myObj)                      // this still === someOtherObj
于 2013-06-12T20:02:48.273 回答