在以下代码中:
function test() {
var x = 5 // scoped to test function
console.log(this); // global object
logCb(function(){
console.log(this); // global object
console.log(x);
})
}
function logCb (cb) {
console.log(this); // global object
cb() // This still seems to execute within the test function scope? why...
}
test()
x的作用域是测试的,这就是定义回调函数的地方。我本来希望cb()
行抛出一个错误,因为logCb()函数无法访问x变量。
然而事实并非如此。为什么?回调中的引用似乎是在赋值期间创建的,而不是在执行期间创建的——我想如果你考虑提升的话,这是有道理的——也就是说,在编译期间,回调函数是否被提升到"测试"的顶部,然后在测试的范围内进行赋值?
我读到执行和范围是不一样的。在本文中:http://ryanmorr.com/understanding-scope-and-context-in-javascript/,这句话scope pertains to the variable access of a function when it is invoked and is unique to each invocation
似乎意味着回调是从测试函数中调用的。
因为在我看来,无论在哪里调用回调函数,它的作用域仍然是要测试的。
我想我的问题是:
在考虑范围和执行上下文时,如何根据定义和调用来处理回调函数?
如何根据定义处理回调函数,然后在考虑范围和执行上下文时调用?
函数范围基于它在词汇环境中的物理位置
解释:回调在函数测试()中存在,因此它总是试图在自己内部(如果存在)找到this的值,否则它将在外部环境中看到它的值(在这种情况下是功能测试)
测试函数和LogCb函数将遵循相同的做法。在这种情况下,外部环境将是全局
引擎如何将范围与执行分开跟踪上下文
词汇环境:在您编写的代码中,某个东西的物理位置。
执行上下文:用于帮助管理正在运行的代码的包装器。
现在,在您的代码中有很多词法环境。当前正在运行的是通过执行上下文进行管理的。它可以包含超出您在代码中所写内容的内容。
无论何时创建执行上下文,我们都有三件事可用:
- 全局对象(窗口):全局范围内的任何变量或函数都链接到窗口对象
- '这个'
- 外部环境
因此,根据当前运行的执行上下文,这些内容将因其在代码中的物理或词汇位置而异。例如,cb
的外部环境是function test()
作用域由创建函数的位置决定,而不是由调用函数的位置决定。
传递给logCb
的函数是在test
内部创建的,因此它可以访问test
的作用域。
在javascript中调用函数时,会向其传递上下文。
上下文可以是的以下方式之一
-
使用new,创建一个临时对象,并将其作为上下文传递给函数
-
通过对象调用函数。getValue()。getValue获取上下文一个
-
如果以上两个都没有通过全局对象即窗口
因为闭包。闭包是词汇环境的功能。词汇环境是指局部变量的集合及其对其父变量的引用。在您的代码中,您在测试函数中定义了回调函数,回调函数将创建一个带有词法环境的闭包,该环境包含对其父变量的引用。通过使用这个闭包,函数仍然可以访问变量x.