Javascript 嵌套函数中的函数上下文(“this”)
在Javascript中调用顶级函数时,函数中的this关键字引用默认对象(如果在浏览器中,则为窗口)。我的理解是,这是作为方法调用函数的一种特殊情况,因为默认情况下,它是在窗口上调用的(如John Resig的书《JavaScript忍者的秘密》第49页所述)。实际上,下面代码中的两个调用是相同的Javascript 嵌套函数中的函数上下文(“this”),javascript,Javascript,在Javascript中调用顶级函数时,函数中的this关键字引用默认对象(如果在浏览器中,则为窗口)。我的理解是,这是作为方法调用函数的一种特殊情况,因为默认情况下,它是在窗口上调用的(如John Resig的书《JavaScript忍者的秘密》第49页所述)。实际上,下面代码中的两个调用是相同的 function func() { return this; } // invoke as a top-level function console.log(func() === window
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
到目前为止还不错。。。下面是我不明白的部分:
当一个函数嵌套在另一个函数中并在未指定要调用的对象的情况下调用时,函数中的this关键字也会引用窗口。但无法在窗口上调用内部函数(请参见下面的代码)
嵌套函数在窗口上不可用是非常合理的,因为它毕竟是嵌套的。。。但我不明白为什么this关键字指的是window,就好像函数是在window上调用的一样。我错过了什么
编辑
下面是对以下重要答案的总结,以及我的一些后续研究
- 如果说“正常”调用函数与作为窗口方法调用函数是一样的,那就不正确了。只有在全局定义函数时,这才是正确的
- 函数上下文(this关键字的值)不取决于函数定义的位置/方式,而是取决于调用函数的方式
- 假设代码未在严格模式下运行,则“正常”调用函数时,函数上下文将设置为“窗口”(在浏览器中运行时,或在其他环境中相应的全局对象)
- 上述规则的一个例外是使用bind创建函数。在这种情况下,即使函数被“正常”调用,它也可能有窗口以外的上下文。也就是说,在这种情况下,上下文由您如何创建函数而不是如何调用函数来确定。虽然严格来说这并不准确,因为bind创建了一个新函数,该函数使用apply在内部调用给定函数。新函数的上下文仍将由其调用方式决定,但它通过使用apply屏蔽其内部调用的函数的上下文
myFunction()代码>
为了完成这幅图,这里简要介绍了其他调用方式和相应的上下文:
- 作为对象(方法)的属性,上下文就是对象
- 使用apply或call-显式指定上下文
- 使用新操作符(作为构造函数)-上下文是一个新创建的对象
如有必要,请随时更新上述内容,以方便有类似问题的人。谢谢 您可以调用functionName()
范围内的任何函数。由于尚未对对象调用它,因此将在默认对象(窗口
)的上下文中调用它。(IIRC,如果您处于严格模式,它将在未定义的上下文中调用)
上下文的默认对象与函数的定义位置或函数出现的范围无关。它只是默认对象
如果函数是对象的属性,则可以将其称为reference.to.object.function()
,它将在object
的上下文中调用,而不是在默认对象中调用
更改上下文的其他内容包括new
关键字和apply
、call
和bind
方法。在JavaScript中,当在没有显式上下文的情况下调用函数时,上下文是全局对象。对于web浏览器,全局对象是window
此外,JavaScript具有函数作用域,因此函数中的任何变量或函数都不能在该函数之外的作用域中访问。这就是您无法访问窗口的原因。调用函数时,innerFunc
函数是否嵌套在另一个函数中与This
的值无关。唯一重要的是:
- 如果通过遍历对象上的属性“找到”函数,则
this
的值将是对该对象的引用:
someObject.prop( whatever );
函数是如何声明的并不重要
- 如果使用
call()
或apply()
调用函数,则this
的值从第一个参数取到您使用的那些函数中的任何一个
- 如果您使用
bind()
为函数创建了绑定包装,则调用bind()
时,this
的值将与请求的值相同
- 如果使用
new
作为构造函数调用函数,则此
将引用新创建的对象实例
- 否则,
此
要么是对全局上下文的引用,要么是未定义的
(在“严格”模式下或在符合ES5的运行时中)
当然,定义函数的代码中的“位置”很重要,因为范围包括它所包含的任何符号,并且这些符号对函数都可用,而不管对函数的引用是如何获得的。它不取决于函数在何处声明,而是取决于函数的调用方式:
var obj = {
f: function() {
return this;
}
}
var f = obj.f;
console.log(obj.f()) // obj
console.log(f()) // window/default obj
或者换句话说。语法obj.f()
使用this=obj
执行函数,而f()
使用this=window
执行函数。在JavaScript中,调用方指定this
的值。当您在全局范围中定义func
时,它实际上被指定为窗口
对象的属性。即,窗口
对象h
var obj = {
f: function() {
return this;
}
}
var f = obj.f;
console.log(obj.f()) // obj
console.log(f()) // window/default obj
var f = obj.func;
f(); // in this call: this === window
var f = obj.func;
f.call(obj); // in this call: this == obj