1

我正在阅读 Angus Croll理解 JS 这个博客并找到了这个

var a = {
  b: function() {
    var c = function() {
      return this;
    };
    return c();
  }
}; 

a.b();//window

在我看来,在调用 c 时,c 在 b 中。那应该是调用上下文(如果我错了,请纠正我)。当它执行时,为什么 c() 的 context(this) 是窗口?

我在那个博客中发现了另一个例子

var a = {
  b: function() {
    return (function() {return this;})();
  }
};

a.b(); //window

为什么 b 的上下文是窗口?匿名函数是否总是在全局上下文中运行?

4

2 回答 2

2

this这是理解(双关语)的好方法:

函数内部的值this由调用函数的方式决定。除了一个例外,它与函数的定义位置、它可能嵌套在其中的其他函数、它被定义为哪个对象、它是什么类型的函数或任何其他函数无关。

foo.bar()当您使用类似or的方法调用来调用函数时foo[bar]()this函数内部就是foo对象。

当您使用普通函数调用(如 )调用函数时foo()this函数中是window对象,或者如果函数使用严格模式,则它是undefined

这是一个例外——如果函数本身或其周围的代码对于普通函数调用进行了"use strict";更改。this对于不应该有所作为的好代码 - 你不应该编写依赖于this对象window的代码。

否则,您关心的是this方法调用中的对象指的是什么。这始终取决于函数的调用方式,而不是它的定义方式。

让我们来看看你的第一个例子。

当您调用 时a.b(),您是b作为a对象的方法调用的。所以在b函数内部,thisa.

碰巧的是,知道这一点对我们没有任何好处,因为该b函数永远不会对this. 它所做的只是c()作为普通函数调用。所以 inside c,this是对象,或者如果您处于严格模式window,它会是对象。undefined

c函数只是返回它的this值,或window。这也是 的返回值b。所以这就是你看到window结果的原因:这一切都来自代码如何调用bandc函数。

现在关于第二个例子:嗯,那只是非常模糊的代码,不是吗?谁会编写这段代码并期望任何人一眼就能理解它?

所以让我们把它变成一种更易读的形式。这条线是问题所在:

    return (function() {return this;})();

让我们取出带括号的函数表达式:

    (function() {return this;})

并将其分配给临时变量:

    var temp = (function() {return this;});

我们不再需要额外的括号,让我们缩进代码以提高可读性:

    var temp = function() {
        return this;
    };

我们可以在语句中将该temp变量称为函数:return

    return temp();

现在我们可以把它放回b代码示例中的函数中:

var a = {
  b: function() {
    var temp = function() {
        return this;
    };
    return temp();
  }
};

a.b(); //window

嘿!这段代码是不是很眼熟?事实上,除了temp变量名之外,它与第一个示例相同。所以现在你明白为什么它和第一个一样了。

于 2013-12-01T06:16:04.993 回答
1

要寻找的一个关键是new关键字,它建立了一个新的上下文。没看到new?然后上下文没有改变,这意味着this没有改变。如果您从内部调用它window,那么这就是您的上下文,这就是您的this. (如果您使用call()apply()使用范围,这会发生变化,但这显然不适用于此处。)

于 2013-12-01T06:20:52.277 回答