【问题标题】:Callback definition closure issue回调定义关闭问题
【发布时间】:2018-03-05 08:35:07
【问题描述】:

关于定义回调的位置,我遇到了一些关于范围界定的困惑。

function test(){

    var b = 3
    var fun = function(){

        var printingFunction = function(){
            console.log(b)
        }
        printingFunction()
    }

    return fun
}

test()() //prints 3, as expected because of closures

但是,以下不起作用

function test(){

    var b = 3
    var fun = function(cb){
        cb()
    }

    return fun
}

test()(function(){console.log(b)}) //b is not defined

我希望由于函数作为参数传递并且之前没有定义,它的定义发生在'fun'中,因此它可以访问b。相反,它看起来很像函数首先在其传递的范围内定义,然后作为参数传递。有什么想法/指针吗?


编辑:一些额外的指针。

someFunction("a")

我们不可能声称“a”是一个定义。这里隐含地发生的是“a”被分配给由参数名称命名的变量,因此var argumentNameInDefintion = "a"。这发生在 someFunction 的主体中。

同样,我们不能声称 {}someFunction({}) 中的定义。那为什么会:

someFunction(function(){})

决定function(){} 是一个超出我的定义。如果是

var a = function(){}
someFunction(a)

一切都会很有意义。也许这正是语言的工作方式。

【问题讨论】:

  • 恕我直言,如果您真的了解闭包,您就会知道为什么第二个示例不起作用。
  • 其实回调函数的作用域就是它定义的地方,不管经过什么调用,它只能从它的作用域访问东西(传入的参数除外)
  • 是的,它们是常量,硬编码常量

标签: javascript closures


【解决方案1】:

JavaScript 中的作用域是词法。如果您查看示例,您会看到定义 printingFunction 的位置,在词法上(例如,在源文本中)b 在包含范围内声明。但在你的第二个例子中,它不是。这就是为什么 b 在您的第二个示例中无法解析,但可以在您的第一个示例中解析。

它的工作方式是,当一个函数被创建时,它会引用一个概念对象,其中包含变量等在它创建的范围内(它有一个花哨的名字:“词法环境对象”);并且该对象具有对包含它的对象的引用。在查找变量引用时,JavaScript 引擎会查看当前的词法环境对象,如果找到该变量,则使用它;否则,它会查找链中的前一个,依此类推,直到全局。

更多细节可以找到:

【讨论】:

  • 是的,但是当您将参数直接传递给函数时,就像 fun("a") 一样,该值被分配给位于函数体内且不存在于其他地方的变量。因此,假设函数作为参数以相同的方式工作,我想不会是这样的延伸。
  • 重要的是函数的定义位置,而不是传递给它的位置。如果您考虑一下,函数的变量分辨率取决于您调用的位置,这充其量是混乱的(并且意味着我们使用闭包的大多数地方都不起作用)。
【解决方案2】:

问题源于我不明白 function(){} 本身就是一个定义,"a"{} 也是如此。由于这些是定义,因此传递的函数的定义范围被适当地放置在它所在的位置,并且世界再次变得有意义。

【讨论】:

    【解决方案3】:

    在第一种情况下,它正在形成一个闭包并可以访问变量“b”,但在第二种情况下,它根本不形成一个闭包。如果您在函数内部的 cb() 之前放置一个调试器,您会注意到没有形成闭包,并且作为回调函数的原因作为参数提供给该函数,并且它成为该函数的本地函数不知道变量 b。

    将其视为两个不同的函数,一个具有局部变量“b”,另一个没有局部变量,但我们试图访问它会引发引用错误。

    【讨论】:

      猜你喜欢
      • 2016-10-16
      • 2020-08-26
      • 1970-01-01
      • 2016-02-10
      • 1970-01-01
      • 2012-03-16
      • 1970-01-01
      • 1970-01-01
      • 2011-05-15
      相关资源
      最近更新 更多