javascript 从类函数中删除类变量

vktxenjb  于 2023-02-07  发布在  Java
关注(0)|答案(3)|浏览(134)

我正在创建一个类,它将被多次重新创建,为了节省内存,我需要彻底删除它。基本上,如果可能的话,我需要访问它的包含变量。
下面是一个例子:

function example(){
  this.id=0;
  this.action=function(){alert('tost');}
  this.close=function(){ delete this;}
}

var foo=new example();
    • 我的问题是**

如何从example函数中访问foo变量以便删除它?

0qx6xfy6

0qx6xfy61#

window.foo将访问该全局变量。

this.close=function(){ delete window.foo; }

但是,我记得有something fishy with global variables, delete and window,所以您可能想用其他方法,例如简单地使用window.foo = null;
如果你想访问另一个函数中定义的变量,你需要读取this SO question的答案。
因为你想要的是允许垃圾收集器释放那个对象,所以你需要确保没有对那个对象的引用,这可能是相当棘手的(也就是不可能的),因为操作对象的代码可以通过全局和局部变量以及属性对它进行多次引用。
您可以通过创建一个代理来访问对象,从而防止直接引用对象,不幸的是javascript不支持动态getter和setter(也称为全捕集)非常好(在某些浏览器上,您可能会实现它,see this SO question),因此您不能轻松地重定向所有字段和方法(无论如何都只是字段)访问底层对象,特别是在底层对象动态添加和删除了许多字段的情况下(即this.anewfield = anewvalue)。
下面是一个简单的代理(代码在jsfiddle.net上):

function heavyobject(destroyself, param1, param2) {
    this.id=0;
    this.action=function(){alert('tost ' + param1 + "," + param2);};
    this.close=function(){ destroyself(); }
}

function proxy(param1, param2) {
    object = null;
    // overwrites object, the only reference to
    // the heavyobject, with a null value.
    destroyer = function() { object = null; };
    object = new heavyobject(destroyer, param1, param2);
    return function(fieldname, setvalue) {
        if (object != null) {
            if (arguments.length == 1)
                return object[fieldname];
            else
                object[fieldname] = setvalue;
        }
    };
}
var foo = proxy('a', 'b');
alert(foo("action")); // get field action
foo("afield", "avalue"); // set field afield to value avalue.
foo("action")(); // call field action
foo("close")(); // call field close
alert(foo("action")); // get field action (should be 'undefined').

它的工作原理是返回一个函数,当用一个参数调用时,获取 Package 对象上的一个字段,当用两个参数调用时,设置一个字段;它的工作原理是确保heavyobject的唯一引用是proxy函数中的object局部变量。
heavyobject中的代码必须 * 永不 * 泄漏this(永不返回它,永不返回一个引用var that = this的函数,永不将它存储到另一个变量的字段中),否则可能会创建一些指向heavyobject的外部引用,从而阻止它被删除。
如果heavyobject的构造函数从构造函数内部(或从构造函数调用的函数)调用destroyself(),则不会有任何效果。
另一个更简单的代理,它会给予你一个空的对象,你可以在上面添加字段,读取字段,和调用方法。我很肯定,使用这个代理,没有外部引用可以逃脱。
代码(也在jsfiddle.net上):

function uniquelyReferencedObject() {
    object = {};
    f = function(field, value) {
        if (object != null) {
            if (arguments.length == 0)
                object = null;
            else if (arguments.length == 1)
                return object[field];
            else
                object[field] = value;
        }
    };
    f.destroy = function() { f(); }
    f.getField = function(field) { return f(field); }
    f.setField = function(field, value) { f(field, value); }
    return f;
}
// Using function calls
o = uniquelyReferencedObject();
o("afield", "avalue");
alert(o("afield")); // "avalue"
o(); // destroy
alert(o("afield")); // undefined
// Using destroy, getField, setField
other = uniquelyReferencedObject();
other.setField("afield", "avalue");
alert(other.getField("afield")); // "avalue"
other.destroy();
alert(other.getField("afield")); // undefined
nnsrf1az

nnsrf1az2#

事实是,您不能删除Javascript中的对象
然后你使用delete运算符,它只接受某个对象的属性,所以,当你使用delete时,通常你必须传递给它类似obj.p的东西,然后你只传递一个变量名,实际上这意味着'全局对象的属性',而delete pdelete window.p相同。不确定delete this内部发生了什么,但结果浏览器就跳过它。
现在,我们用delete实际上删除了什么?我们删除了一个对象的引用。这意味着对象本身仍然在内存中。为了消除它,你必须删除所有对具体对象的引用。所有引用-从其他对象,从闭包,从事件处理程序,链接数据,所有这些。但是对象本身没有关于所有这些引用的信息。因此无法从对象本身删除对象。请看以下代码:

var obj = <our object>;
var someAnother = {
       ...
       myObjRef: obj
       ...
 }
var someAnotherAnother = {
       ...
       secondRef : obj
       ...
}

为了从内存中删除obj,你必须删除someAnother.myObjRefsomeAnoterAnother.secondRef。你只能从program的一部分中删除它们。
如果我们可以有任意数量的引用,我们如何删除一些东西呢?有一些方法可以解决这个问题:

  • 在程序中只设置一个点,这个对象将被引用。事实上,在我们的程序中只有一个引用。然后我们删除它-对象将被垃圾收集器杀死。这是上面描述的“代理”方式。这有它的缺点(语言本身还不支持,并且必须将cool and nice obj.x=1更改为obj.val('x',1)。此外,这一点不太明显,事实上你把所有对obj的引用都改成了对proxy的引用。proxy将永远保留在内存中而不是object。根据对象的大小,对象的数量和实现,这可以给你带来一些好处,或者甚至使事情变得更糟。例如,如果你的对象的大小接近proxy本身的大小-你将没有任何价值。
  • 在你使用对象的每一个地方添加一个代码,这个代码将删除对这个对象的引用。它使用起来更清楚和简单,因为如果你在某个地方调用一个obj.close()--你已经知道了删除它所需要的一切。只是代替obj.close()来杀死对它的引用。一般来说--把这个引用改为另一个东西:
var x = new obj; //now our object is created and referenced
  x = null;// now our object **obj** still im memory 
  //but doest have a references to it 
  //and after some milliseconds obj is killed by GC...

  //also you can do delete for properties
  delete x.y; //where x an object and x.y = obj

但使用这种方法时,你必须记住引用可能出现在很难理解的地方。2例如:

function func() {
     var x= new obj;// our heavy object
     ...
     return function result() {
         ...some cool stuff..
     }
  }

引用存储在result函数的闭包中,当您在某处引用result时,obj将保留在内存中。

  • 很难想象物体本身很重,最现实的情况是-你有一些数据在里面。在这种情况下,你可以添加一个清理功能的对象,这将清理这些数据。假设你有一个巨大的缓冲区(例如数字数组)作为对象的属性,如果你想释放内存-你可以清除这个缓冲区,这个缓冲区里的对象仍然有几十个字节,记住把你的函数放到prototype中,以保持示例的小。
72qzrwbm

72qzrwbm3#

这里有一个链接,指向有关JavaScript删除操作符的一些非常详细的信息。
http://perfectionkills.com/understanding-delete/

相关问题