嵌套函数中的函数上下文(“this”) [英] Function context ("this") in nested functions

查看:90
本文介绍了嵌套函数中的函数上下文(“this”)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当您在Javascript中调用顶级函数时,函数内的 this 关键字将引用默认对象(如果在浏览器中,则为窗口)。我的理解是,这是一个调用函数作为方法的特殊情况,因为默认情况下它是在窗口上调用的(如John Resig的书中所述,JavaScript忍者的秘密,第49页)。实际上,以下代码中的两个调用都是相同的。

When you invoke a top-level function in Javascript, the this keyword inside the function refers to the default object (window if in a browser). My understanding is that it's a special case of invoking the function as method, because by default it is invoked on window (as explained in John Resig's book, Secrets of the JavaScript Ninja, page 49). And indeed both invocations in the following code are identical.

function func() {
  return this;
}

// invoke as a top-level function
console.log(func() === window); // true

// invoke as a method of window
console.log(window.func() === window); // true

到目前为止很好......现在这里是我不理解的部分:

So far so good... Now here is the part I don't understand:

当一个函数嵌套在另一个函数中并在没有指定要调用的对象的情况下调用时,函数内的 this 关键字也指向窗口。但是不能在窗口上调用内部函数(参见下面的代码)。

When a function is nested in another function and invoked without specifying an object to invoke on, the this keyword inside the function also refers to window. But the inner function cannot be invoked on window (see code below).

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

  // invoke without window.* - OK
  console.log(innerFunc() === window); // true

  // invoke on window
  //window.innerFunc(); - error (window has no such method)
  console.log(window.innerFunc) // undefined
}

outerFunc();

完全合理的是嵌套函数在窗口上不可用,因为它是在所有嵌套之后...但后来我不明白为什么this关键字引用窗口,好像在窗口上调用了该函数。我在这里缺少什么?

It makes perfect sense that the nested function isn't available on window, as it is after all nested... But then I don't understand why the this keyword refers to window, as if the function was invoked on window. What am I missing here?

编辑

以下是下面的答案和我的一些后续研究。

Here is a summary of the great answers below and some of my follow up research.


  • 说正常调用函数是错误的与将其作为 window 的方法调用相同。只有在全局定义函数时,这才是正确的。

  • It is incorrect to say that invoking a function "normally" is the same as invoking it as a method of window. This is only correct if the function is defined globally.

函数上下文( this 关键字的值)不依赖于关于函数定义的位置和方式,以及如何调用函数。

The function context (the value of the this keyword) does not depend on where / how the function is defined, but on how it is being invoked.

假设代码没有在严格模式下运行,调用函数normal将函数上下文设置为window(在浏览器中运行时,或其他环境中相应的全局对象)。

Assuming that the code is not running in in strict mode, Invoking a function "normally" will have the function context set to to window (when running in a browser, or the corresponding global object in other environments).

例外上面的规则是使用 bind 来创建一个函数。在这种情况下,即使正常调用该函数,它也可能具有 window 以外的上下文。也就是说,在这种情况下,上下文由您创建函数的方式决定,而不是如何调用它。虽然严格来说这是不准确的,因为 bind 会创建一个新函数,使用 apply 在内部调用给定函数。该新函数的上下文仍将由其调用的方式决定,但它通过使用 apply 屏蔽其内部调用的函数的上下文。

An exception to the above rules is the use of bind to create a function. In this case even if the function is invoked "normally", it could have a context other than window. That is, in this case the context is determined by how you create the function, rather than how you invoke it. Although strictly speaking this isn't accurate, because bind creates a new function that internally invokes the given function using apply. The context of that new function will still be determined by the way it's invoked, but it shields the context of the function it internally invokes by using apply.

通过调用normal,我引用以下简单的调用方式:

By invoking "normally" I refer to the following simple way of invocation:

myFunction();

为了完成图片,这里简要介绍了其他调用方式和相应的上下文:

To complete the picture, here is a brief coverage of other ways of invocation and the corresponding context:


  • 作为对象(方法)的属性 - 上下文是对象

  • As a property of an object (method) - the context is the object

使用apply或call - 显式指定上下文

Using apply or call - the context is specified explicitly

使用 new 运算符(作为构造函数) - 上下文是一个新创建的对象

With the new operator (as a constructor) - the context is a newly created object

根据需要随意更新上述内容,以便为类似的人提供帮助的问题。谢谢!

Feel free to update the above as necessary, for the benefit of people with similar questions. Thanks!

推荐答案

您可以使用 functionName()。由于您尚未在对象上调用它,因此将在默认对象( window )的上下文中调用它。 (IIRC,如果您处于严格模式,它将在 undefined 的上下文中调用。)

You can call any function that is in scope with functionName(). Since you haven't called it on an object, it will be called in the context of the default object (window). (IIRC, it will be called in the context of undefined if you are in strict mode).

默认值上下文的对象与定义函数的位置或函数出现的范围无关。它只是默认对象。

The default object for context has nothing to do with where a function is defined or what scope that function appears in. It is simply the default object.

如果函数是属性一个对象,您可以将其称为 reference.to.object.function(),它将在 object 而不是默认对象。

If a function is a property of an object, you can call it as reference.to.object.function(), and it will be called in the context of object instead of the default object.

更改上下文的其他内容是 new 关键字和 apply call bind methods。

Other things that change the context are the new keyword and the apply, call, and bind methods.

这篇关于嵌套函数中的函数上下文(“this”)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆