所以我正在玩回调的概念,我遇到了一个情况,我想确定我知道我认为发生了什么,实际上是在发生。
function greet(callback) { // 'greet' function takes a callback
var greeting = "hi"; // 'greeting' variable is set in the scope
callback() // 'callback' function is invoked
}
greet(
function() {
console.log(greeting)
});
//Console logs nothing
Sorta很奇怪,你希望callback()能够查看下一个最接近的范围并找出问候语。但是,一旦我将greeting变量声明为全局执行上下文,就会在控制台中记录问候语。
var greeting = 'hi' // 'greeting' variable is set in global context
function greet(callback) { // 'greet' function takes a callback
callback() // 'callback' function is invoked
}
greet(
function() {
console.log(greeting)
});
//Console logs: 'hi'
这是因为从技术上讲,记录变量的callback()函数实际上是在全局上下文中定义的,只是在greet()中调用吗?因此,它不会像普通函数表达式那样首先查看greet(),而是直接进入全局上下文,因为它就是定义它的位置。
我只是想确保我理解这里发生了什么,而不是一些我没有意识到的奇怪的范围/块问题。
答案 0 :(得分:1)
这是词法范围的一个例子,它是JavaScript处理范围的方式,而不是动态范围。简而言之,词汇范围根据事物的定义来确定上下文,动态是基于它被调用的位置。
你的第一个例子就像你认为的那样是动态范围。
您可以在"词汇范围与动态范围"中阅读更多细节。部分。
答案 1 :(得分:1)
你是对的 - 该函数可以访问它所定义的范围。
你的例子实际上是这个(将你的回调移动到它自己的函数):
var greeting = 'hi';
function greet(callback) {
callback();
}
function logGreeting() {
console.log(greeting);
}
greet(logGreeting);
如您所见,logGreeting
此时可以访问greeting
,因为它是在相同(或更高)范围内定义的。
然而,当我们将greeting
移入greet
函数时:
function greet(callback) {
var greeting = 'hi';
callback();
}
function logGreeting() {
console.log(greeting);
}
greet(logGreeting);
greeting
已不再与logGreeting
相同或更高的范围,它完全在不同的范围内,因此logGreeting
无法向上查看范围以便找到greeting
。
logGreeting
可以访问的范围是定义它的范围而不是它被调用的范围,因此当用{{1}调用范围时它不会评估范围就像你在问题中提到的那样。
答案 2 :(得分:0)
Javascript使用 静态范围
TLDR; 变量根据其在源代码中的位置进行解析。
greeting
仅通过greet
函数的闭包来定义。只有greet
函数闭包中定义的代码才能看到greeting
变量。
function greet(callback) { // 'greet' function takes a callback
var greeting = "hi"; // 'greeting' variable is set in the scope
callback() // 'callback' function is invoked
}
greet(function() {
console.log(greeting)
});
此处,greeting
在greet
函数的嵌套闭包和console.log
调用中使用的匿名函数可访问的作用域中定义。
var greeting = 'hi' // 'greeting' variable is set in global context
function greet(callback) { // 'greet' function takes a callback
callback() // 'callback' function is invoked
}
greet(function() {
console.log(greeting)
});
注意: 此关键字有一组不同的规则。