通过私有函数和自执行函数来理解JavaScript



我在阅读Angus Croll理解JS的博客时发现了这个

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

在我看来,在调用c的时候,c在b内部。这应该是调用上下文(如果我错了,请纠正我)。当它执行时,为什么c()的上下文(this)是window?

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

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

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

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

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

当使用类似foo.bar()foo[bar]()的方法调用函数时,函数内的thisfoo对象。

当使用普通函数调用(如foo())调用函数时,函数中的thiswindow对象,或者如果函数使用严格模式,则为undefined

这是一个例外——如果函数本身或其周围的代码具有"use strict";,那么它会为普通函数调用更改this。对于不应该有区别的好代码,您不应该编写依赖于this作为window对象的代码。

否则,您关心的是this在方法调用中引用了什么对象。这总是由函数的调用方式决定的,而不是它的定义方式。

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

当您调用a.b()时,您将调用b作为a对象的方法。因此,在b函数中,thisa相同。

碰巧的是,知道这一点对我们没有任何好处,因为b函数从未对this做过任何事情。它所做的只是将c()作为一个普通函数调用。因此,在c中,thiswindow对象,或者如果您处于严格模式,它将是undefined

c函数只是返回其this值或window。这也是b的返回值。这就是为什么您看到window作为结果:这一切都来自于代码如何调用bc函数。

现在来看第二个例子:好吧,这只是非常模糊的代码,不是吗?谁会写下这段代码,并期望任何人第一眼就能理解它?

所以让我们把它变成一个可读性更强的形式

    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变量的名称之外,它与第一个示例完全相同。现在你明白为什么它和第一个一样工作了。

需要查找的一个关键字是new关键字,它建立了一个新的上下文。没有看到new?那么上下文没有改变,这意味着this没有改变。如果你在window中调用它,那么这就是你的上下文,那就是你的this。(如果将call()apply()与作用域一起使用,则情况会发生变化,但这显然不适用于此处。)

相关内容

  • 没有找到相关文章

最新更新