由于我用javascript的时髦“对象模型”处理过去,我认为没有析构函数这样的东西。我的搜索有点不成功,所以你们是我最后的希望。你如何在实例销毁时执行东西?
答案 0 :(得分:27)
MDN是JS的一个很好的资源。 不,当对象停止时,没有什么比调用函数更好的了。
答案 1 :(得分:0)
从最近开始,this link在回答这个问题上更有用。最重要的部分:
从2012年开始,所有现代浏览器均提供标记浏览功能 垃圾收集器。
...
周期不再是问题
在上面的第一个示例中,函数调用返回后,两个 对象不再由任何可访问的资源引用 来自全局对象。因此,将发现它们无法访问 由垃圾收集器回收并分配了分配的内存。
限制:手动释放内存
有时候方便手动决定何时 以及释放的内存。为了释放一个 对象,则必须使其明确不可访问。
就循环引用而言,并不需要解构子。
我想过一个很酷的技巧,如果您有循环引用,并且想要轻松的手动控制来进行解构...
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();
因此,在这里,它不是存储包含对Container实例的直接引用的Containee类,而是存储了对包含容器引用的大小为1的数组的引用,然后容器实例本身可以从中删除自己。带有引用的数组由Container管理。
但是再次重申,实际上并不需要,因为所有现代浏览器中的垃圾回收都是按标记清除的,并且可以处理循环引用。
答案 2 :(得分:0)
在其他语言中,析构函数很容易实现memento模式。这实际上就是引导我进入这个话题的原因。例如,在click事件中,最好有一个通用函数,我可以将事件目标传递给该函数,以禁用目标,然后在超出范围时重新启用它。考虑执行以下操作的提交按钮:
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 }
}
这种构造会给我一个oneliner,当我与后端对话或进行任何其他处理时,它可以处理启用/禁用我所有的按钮。如果我回到中间某处或类似的地方,我不必担心清理。
答案 3 :(得分:0)
FinalizationRegistry 可能正是您所需要的。它不是析构函数,但是一旦对象被垃圾回收,它就会执行一个函数。无论如何,这就是我第一次来到这里时希望找到的东西:)