【问题标题】:Callback/scope understanding回调/范围理解
【发布时间】:2017-05-19 22:47:47
【问题描述】:

所以我在玩回调的概念,我遇到了一种情况,我想确保我知道我认为正在发生的事情,实际上正在发生的事情。

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

有点奇怪,你会期望 callback() 在下一个最接近的范围内查看并找出问候语是什么。但是,一旦我向全局执行上下文声明了问候语变量,问候语就会记录在控制台中。

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() 的内部,而是直接查看全局上下文,因为这是定义它的地方。

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

【问题讨论】:

标签: javascript


【解决方案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 可以访问的范围是定义它的范围,而不是调用它的范围,因此它不会在使用 callback() 调用时评估范围,就像您在问题中提到的那样。

【讨论】:

    【解决方案2】:

    这是一个词法作用域的例子,它是 JavaScript 处理作用域的方式,而不是动态作用域。简而言之,词法作用域根据定义事物的位置确定上下文,而动态则根据调用的位置确定。

    让您的第一个示例像您认为的那样工作是动态范围。

    您可以在“词汇范围与动态范围”部分阅读更多详细信息。

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-04
        • 2014-02-14
        • 2014-01-11
        相关资源
        最近更新 更多