在嵌套函数,作为参数传递的函数以及返回的函数的系统中,调用堆栈是什么样的?

问题描述

这是嵌套函数一个组成示例,其中嵌套函数以参数形式传递并返回函数

function foo() {
  let x = 100
  function bar(a,b) {
    function mul(cb) {
      let m = x * a
      cb(m)
    }

    function add(cb) {
      let m = x + b
      cb(m)
    }

    function update(m) {
      x = m
    }
    
    mul(update)
    add(update)

    console.log(x)
  }
  return bar
}

let bar = foo()
bar(2,3) // => 203
bar(2,3) // => 409
bar(2,3) // => 821
bar(2,3) // => 1645

没有找出巧妙的编译器可以优化和/或减少/简化这些功能的潜在方式,天真的编译器将如何在带有激活记录的调用堆栈中表示这些功能 >

  • bar是从父函数返回的嵌套函数。即使父作用域现已“关闭”,它也会使用父作用域中的x
  • mul使用来自父父范围的x和来自父范围的a。此外,它还需要一个回调cb,该回调函数可以更新x
  • addmul相似。

我一直在在线阅读有关activation records work的方式,并获得如何使用简单堆栈在JavaScript(在JavaScript VM中)实现它们的方法。但是,我还没有找到任何好的资源来解释如何实现嵌套函数以及将函数作为参数实现,就像我上面发布的示例一样。看来这些与non-local variables有关,但是关于这些的信息并不多。与nested functions相同。例如,维基百科说:

语言运行时代码还必须隐式传递该函数在其封装函数内部看到的环境(数据),以便在当前不存在该封装函数的情况下也可以访问该环境。这意味着该环境必须存储在另一个存储区域中,而不是基于时序的执行堆栈中(随后回收的部分)中,这又意味着某种自由动态的内存分配。

但是,除了说它是“ closure”之外,它并没有解释实际的情况。 This的实践细节也不够。

基本上,我想知道调用堆栈如何看待示例中的不同点,例如以下步骤:

  1. foo -> bar -> mul
  2. foo -> bar -> mul -> update
  3. foo -> bar -> console.log(x)

例如,foo -> bar -> mul表示函数调用堆栈和激活记录在上述代码中说let m = x * a的步骤中是什么样子?等。 >

我了解您需要以某种方式保留对父级“范围”的引用,但是实际上这是什么样的(例如,如果要以JSON或使用JavaScript伪代码显示它)?并且由于函数barreturn的{​​{1}},因此我们保留foo的本地语言,但是foo返回了。这对堆栈有什么作用?

我想了解这一点,因为我正在实现一种编程语言。我希望该语言支持我上面概述的所有JavaScript功能,但是我想像在VM中或使用Assembly或类似工具那样在底层实现它,因此需要了解调用堆栈在此高级系统中的功能

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)