简体   繁体   English

Javascript 相当于对象模型中的 destruct

[英]Javascript's equivalent of destruct in object model

Since I've dealt in the past with javascript's funky "object model", I assume there is no such thing as a destructor.由于我过去处理过 javascript 的时髦“对象模型”,因此我认为没有析构函数这样的东西。 My searches were mildly unsuccessful, so you guys are my last hope.我的搜索有点不成功,所以你们是我最后的希望。 How do you execute stuff upon instance destruction?你如何在实例销毁时执行东西?

MDN is a nice resource for JS. MDN是一个很好的 JS 资源。 No, there is nothing like calling a function when an object ceases.不,没有什么比在对象停止时调用函数更合适的了。

As of more recently, this link is of more use to answer this question.最近, 此链接更适用于回答此问题。 The most important part:最重要的部分:

As of 2012, all modern browsers ship a mark-and-sweep garbage-collector.截至 2012 年,所有现代浏览器都提供了标记和清除垃圾收集器。

... ...

Cycles are no longer a problem周期不再是问题

In the first example above, after the function call returns, the two objects are no longer referenced by any resource that is reachable from the global object.在上面的第一个示例中,在函数调用返回后,这两个对象不再被可从全局对象访问的任何资源引用。 Consequently, they will be found unreachable by the garbage collector and have their allocated memory reclaimed.因此,垃圾收集器将发现它们无法访问并回收分配的内存。

Limitation: Releasing memory manually限制:手动释放内存

There are times when it would be convenient to manually decide when and what memory is released.有时手动决定何时以及释放什么内存会很方便。 In order to release the memory of an object, it needs to be made explicitly unreachable.为了释放一个对象的内存,它需要明确地不可达。

So as far as cyclic references goes, de[con]structors aren't really needed.因此,就循环引用而言,实际上并不需要 de[con]structors。


One cool trick I have thought of though, if you have cyclic references and you want easy manual control over deconstruction...不过,我想到了一个很酷的技巧,如果您有循环引用并且想要轻松手动控制解构...

class Container {
  constructor() {
    this.thisRef = [ this ];
    this.containee = new Containee({ containerRef: this.thisRef });
  }

  //Note: deconstructor is not an actual JS thing/keyword.
  deconstructor() {
    //Have to delete `this.thisRef[0]` and not `this.thisRef`, in
    //order to ensure Containee's reference to Container is removed.
    delete this.thisRef[0];
  }

  doSomething() {

  }
}

class Containee {
  constructor({ containerRef }) {
    //Assumption here is, if the Container is destroyed, so will the Containee be
    //destroyed. No need to delete containerRef, no need for a
    //deconstructor function!
    this.containerRef = containerRef;
  }

  someFunc() {
    this.containerRef[0].doSomething();
  }
}

let c = new Container();
...
//No cyclic references!
c.deconstructor();

So here, instead of the Containee class storing a direct reference to the Container instance, it stores a reference to a size 1 array containing the Container reference, which the Container instance itself can then delete itself from .因此,在这里,不是 Container 类存储对 Container 实例的直接引用,而是存储对包含 Container 引用的大小为 1 的数组的引用,然后 Container 实例本身可以从 中删除自己 The array, with the reference, is managed by Container.带有引用的数组由 Container 管理。

But again, this isn't really needed , since garbage collection in all modern browsers is mark-and-sweep and can handle cyclic references.但同样,这并不是真正需要的,因为所有现代浏览器中的垃圾收集都是标记和清除并且可以处理循环引用。

In other languages the destructor is handy for implementing the memento pattern.在其他语言中,析构函数对于实现备忘录模式很方便。 That's actually what lead me to this topic.这实际上是导致我进入这个话题的原因。 For example, in a click event it'd be nice to have a generic function that I can pass the event target to that disables the target and then re-enables it when it falls out of scope.例如,在点击事件中,最好有一个通用函数,我可以将事件目标传递给禁用目标,然后在它超出范围时重新启用它。 Consider a submit button that does something like this:考虑一个执行如下操作的提交按钮:

function async saveMyStuff(e) {
    const sleeper = new nap(e)
    let data = await fetch(...)
    // a bunch more code.
}

class nap {
    constructor(e) {
      this.button = e.currentTarget
      this.button.disabled = true
    }
    destructor() { this.button.enabled = true }

} }

This kind of construct would give me a oneliner that handles enabling/disabling all of my buttons when I'm talking to the backend or doing any other processing.这种构造会给我一个oneliner,当我与后端交谈或进行任何其他处理时,它可以处理启用/禁用我的所有按钮。 I don't have to worry about cleaning up if I return somewhere in the middle or anything like that.如果我在中间的某个地方或类似的地方返回,我不必担心清理。

FinalizationRegistry might be what you need. FinalizationRegistry可能正是您所需要的。 It is not a destructor, but it executes a function once the object is garbage collected.它不是析构函数,但是一旦对象被垃圾回收,它就会执行一个函数。 In any case, this is what I wish I had find when I first came on here :)无论如何,这就是我第一次来到这里时希望找到的东西:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM