愿所有的美好和期待都能如约而至

JS闭包上下文对象的寿命?

发布时间:  来源:互联网  作者:匿名  标签:closures error Lifespan of JS closure context objects? exception garbage-collect  热度:37.5℃

本文介绍了JS闭包上下文对象的寿命?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

我正在尝试将灵丹妙药的参与者模型语言原语移植到JS中。我想出了一个解决方案(在JS中)来模拟receiveelxir关键字,使用"Receiver&Quot;函数和生成器。

这里是一个简化的实现和演示,向您展示这一想法。

接口

type ActorRef: { send(msg: any): void }
type Receiver = (msg: any) => Receiver
/**
 * `spawn` takes a `initializer` and returns an `actorRef`.
 * `initializer` is a factory function that should return a `receiver` function.
 * `receiver` is called to handle `msg` sent through `actorRef.send(msg)`
 */
function spawn(initializer: () => Receiver): ActorRef

演示

function* coroutine(ref) {
  let result
  while (true) {
    const msg = yield result
    result = ref.receive(msg)
  }
}

function spawn(initializer) {
  const ref = {}
  const receiver = initializer()
  ref.receive = receiver
  const gen = coroutine(ref)
  gen.next()

  function send(msg) {
    const ret = gen.next(msg)
    const nextReceiver = ret.value
    ref.receive = nextReceiver
  }

  return { send }
}

function loop(state) {
  console.log('current state', state)
  return function receiver(msg) {
    if (msg.type === 'ADD') {
      return loop(state + msg.value)
    } else {
      console.log('unhandled msg', msg)
      return loop(state)
    }
  }
}

function main() {
  const actor = spawn(() => loop(42))
  actor.send({ type: 'ADD', value: 1 })
  actor.send({ type: 'BLAH', value: 1 })
  actor.send({ type: 'ADD', value: 1 })
  return actor
}

window.actor = main()

问题

上面的模型是可行的。但是,我有点担心这种方法的性能影响,我不清楚它创建的所有闭包上下文对内存的影响。

function loop(state) {
  console.log('current state', state) // <--- `state` in a closure context  <─┐    <─────┐
  return function receiver(msg) {     // ---> `receiver` closure reference  ──┘          │
    if (msg.type === 'ADD') {                                                            │
      return loop(state + msg.value)  // ---> create another context that link to this one???
    } else {
      console.log('unhandled msg', msg)
      return loop(state)
    }
  }
}

loop是返回&quot;Receiver&Quot;的&quot;初始值设定项&quot;。为了维护内部状态,我将其(state变量)保存在&quot;Receiver&Quot;函数的闭包上下文中。

收到消息时,当前接收方可以修改内部状态,传递给loop,并递归创建一个新接收方替换当前接收方。

显然,新的接收器也有一个新的闭包上下文来保持新的状态。在我看来,此过程可能创建阻止GC的链接上下文对象的深链?

我知道闭包引用的上下文对象在某些情况下可以链接。如果它们是联系在一起的,显然在最里面的闭合被释放之前,它们不会被释放。根据this articleV8优化在这方面是非常保守的,画面看起来不太好。

问题

如果有人能回答这些问题,我将不胜感激:

  1. loop示例是否创建深度链接的上下文对象?
  2. 本例中上下文对象的寿命是多少?
  3. 如果当前示例没有,此receiver创建receiver机制是否会在其他情况下最终创建深度链接的上下文对象?
  4. 如果问题3是,您能举一个例子来说明这种情况吗?

跟进1

@TJCrowder的后续问题。

闭包是词法的,所以它们的嵌套跟在源代码的嵌套之后。

说得好,这是显而易见的,但我很怀念

勇敢去编程!

勇敢的热爱编程,未来的你一定会大放异彩,未来的生活一定会因编程更好!

TOP