JavaScript:通过类方法创建和销毁类实例
Posted
技术标签:
【中文标题】JavaScript:通过类方法创建和销毁类实例【英文标题】:JavaScript: Create and destroy class instance through class method 【发布时间】:2014-02-02 19:57:43 【问题描述】:我试图弄清楚如何通过类方法删除对象。我希望能够创建一个具有从内存中释放对象的销毁方法的类。到目前为止,我所做的研究还没有定论。我知道垃圾收集最终会处理该对象,但我想要一种更明确的方式来销毁它。这可能吗?
// class constructor
var class = function ()
this.destroy = function () ;
;
// instance
var instance = new class();
instance.destroy();
console.log(instance); // should be null or undefined
【问题讨论】:
How to have an instance delete itself from within a prototype function is javascript 的可能重复项 这种问题似乎来自对对象实例如何生存和死亡的误解。这根本不是 JS 的工作方式,但这并不意味着它是一个限制。这意味着事情需要以不同的方式完成。那么你在这里的真正目标是什么? 我的目标是快速删除对象,包括事件处理程序以及由于创建对象而创建的任何内容。 @尼克C 看看我的回答,我想你会得到你想要的。 我不是SO的常客,所以这么晚才遇到。我经常看到人们试图确定类的范围,但使用 document.head.appendChild() 将其加载到文档中。这将注册,并且 eval() - 即使 eval.call(,js) 将使用窗口范围来查找类。相反,不要将它添加到文档中(如果你是的话),而是使用类似 eval.call(,'class myclass (function() return new MyClass())()') 来评估整个类.这不应该使用窗口,您可以随时替换 MyClass。 【参考方案1】:1- 无法在 javascript 中实际销毁对象,但使用delete
,我们可以从对象中删除引用:
var obj = ;
obj.mypointer = null;
delete obj.mypointer;
2- 关于delete
关键字的重要一点是,它实际上并没有销毁对象,但如果仅在删除对该对象的引用之后,内存中没有其他指向同一对象的引用,即对象将被标记为可收藏。 delete
关键字删除引用但不 GC 实际对象。这意味着如果您对同一个对象有多个引用,则该对象将在您删除所有指向的引用后立即被收集。
3- 当我们想要确保不会留下任何内存泄漏时,还有一些技巧和解决方法可以帮助我们。例如,如果您有一个包含多个对象的数组,而没有任何其他指向这些对象的引用,那么如果您重新创建该数组,所有这些对象都将被杀死。例如,如果您有 var array = [, ]
覆盖数组的值,如 array = []
将删除对数组内两个对象的引用,这两个对象将被标记为可收集。
4- 对于您的解决方案,最简单的方法就是:
var storage = ;
storage.instance = new Class();
//since 'storage.instance' is your only reference to the object, whenever you wanted to destroy do this:
storage.instance = null;
// OR
delete storage.instance;
如上所述,设置storage.instance = null
或delete storage.instance
就足以删除对对象的引用并允许GC 清理它。不同之处在于,如果将其设置为null
,则存储对象仍然有一个名为 instance 的属性(值为 null)。如果你delete storage.instance
则存储对象不再具有名为实例的属性。
和破坏方法怎么样??
这里的矛盾点是,如果您在销毁函数中使用instance.destroy
,您将无法访问实际的instance
指针,并且它不会让您删除它。
唯一的办法是将引用传递给destroy函数,然后将其删除:
// Class constructor
var Class = function ()
this.destroy = function (baseObject, refName)
delete baseObject[refName];
;
;
// instanciate
var storage = ;
storage.instance = new Class();
storage.instance.destroy(object, "instance");
console.log(storage.instance); // now it is undefined
但是如果我是你,我会坚持第一个解决方案并像这样删除对象:
storage.instance = null;
// OR
delete storage.instance;
哇,太多了:)
【讨论】:
@vsync 如果它没有附加到任何对象或变量,那么一旦它运行完任何代码就会被收集。例如,如果您执行(new SomeObject).doSomething)
,那么它将在执行完doSomething
后被收集。如果该对象有一个setTimeout
调用或任何其他触发异步逻辑的东西,那么 SomeObject 在其他任务完成之前不会被收集(除非这些任务不包含对 SomeObject 实例或任何其他属于 SomeObject 的引用实例)。
@vsync 假设doSomething
方法设置了一个setInterval
,它执行console.log(this)
,那么setInterval 将永远运行并且SomeObject 将永远不会被收集,除非该间隔具有将clearInterval
在某个时候。基本上,如果一个对象没有运行(或正在运行)的代码,也没有对它的引用,它将被收集。
这个答案不正确。 javascript 中的delete keyword 从对象中删除属性。它不直接释放内存,也不破坏对象。如果是这样,那么在调用 delete
之前将引用设置为 null 是没有意义的。
@DavidMills 感谢您让我知道我多年前的这个错误答案,我做了一些更改,请您检查一下以确保它现在是否有意义?
在storage.instance
的例子中,如果你想让GC清理instance
对象,那么或者设置storage.instance = null
或者 i> delete storage.instance
足以删除对对象的引用并允许它被 GC 清理。不同之处在于,如果将其设置为null
,那么storage
对象仍然有一个名为instance
的属性(值为null
)。如果您 delete storage.instance
则 storage
对象不再具有名为 instance
的属性。【参考方案2】:
没有。 JavaScript 会自动进行垃圾回收;只有当 GC 决定运行并且对象符合回收条件时,才会回收对象的内存。
既然这将根据需要自动发生,那么显式回收内存的目的是什么?
【讨论】:
我想快速删除创建对象时创建的事件处理程序、引用等。 @user699242:再说一遍,为什么?如果除了对象之外没有人引用这些东西,那么回收对象也将允许回收这些东西。除了“丢失”对对象的所有引用之外,您无需执行任何操作。为什么要手动操作? 我猜“失去所有对对象的引用”对我来说是模棱两可的。什么时候发生?对不起,这一直让我很困惑 换句话说,我是否需要做任何事情来“释放参考”。例如将指针设置为 null 或... 枚举的可能性太多了,但总的来说“将那个东西设置为null
”会起作用。然而,这是你应该更好地处理的事情,因为它可以在内存泄漏到崩溃镇之间产生差异。你真的必须尝试那样泄漏,但是......【参考方案3】:
您只能手动删除对象的属性。因此:
var container = ;
container.instance = new class();
delete container.instance;
但是,这不适用于任何其他指针。因此:
var container = ;
container.instance = new class();
var pointer = container.instance;
delete pointer; // false ( ie attempt to delete failed )
此外:
delete container.instance; // true ( ie attempt to delete succeeded, but... )
pointer; // class destroy: function()
因此在实践中,删除仅对删除对象属性本身有用,而不是从内存中删除它们指向的代码的可靠方法。
手动指定的destroy
方法可以取消绑定任何事件侦听器。比如:
function class()
this.properties = /**/
function handler() /**/
something.addEventListener( 'event', handler, false );
this.destroy = function()
something.removeEventListener( 'event', handler );
【讨论】:
这不是 = void 0;左手分配无效? 你说得对。这也是一个非常愚蠢的想法,因为即使它确实有效,它所能做的只是由于缺少指针而导致错误。以上是关于JavaScript:通过类方法创建和销毁类实例的主要内容,如果未能解决你的问题,请参考以下文章
java中静态成员变量、实例变量、局部变量何时创建、何时销毁?