回调/范围理解

时间:2017-05-19 22:47:48

标签: javascript

所以我正在玩回调的概念,我遇到了一个情况,我想确定我知道我认为发生了什么,实际上是在发生。

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(),而是直接进入全局上下文,因为它就是定义它的位置。

我只是想确保我理解这里发生了什么,而不是一些我没有意识到的奇怪的范围/块问题。

3 个答案:

答案 0 :(得分:1)

这是词法范围的一个例子,它是JavaScript处理范围的方式,而不是动态范围。简而言之,词汇范围根据事物的定义来确定上下文,动态是基于它被调用的位置。

你的第一个例子就像你认为的那样是动态范围。

您可以在"词汇范围与动态范围"中阅读更多细节。部分。

https://en.wikipedia.org/wiki/Scope_(computer_science)

答案 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)
}); 

此处,greetinggreet函数的嵌套闭包和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)
});

注意: 关键字有一组不同的规则。