JavaScript新关键字和内存管理

时间:2010-03-08 16:02:00

标签: javascript memory-management garbage-collection

来自C ++,我很难想到每次拨打new时我都会调用delete。在JavaScript中,我发现自己偶尔会在我的代码中调用new但是(希望)浏览器中的垃圾收集功能会为我处理这些混乱。

我不喜欢这个 - JavaScript中是否有delete方法,我是如何使用它与C ++中的不同?

感谢。

11 个答案:

答案 0 :(得分:24)

var component = new Component();
component = null; // delete this at next garbage collection

答案 1 :(得分:13)

顺便说一句,“new”关键字在javascript中并不是必需的,并且没有(直接)与分配内存有关。所有“new”都会传递一个名为“this”(this = {})的新空对象作为函数的隐藏参数。

var MyClass = function(){
    // fresh empty object "this" gets passed to function
    // when you use the "new" keyword 
    this.method = function(){}
}

var myInstance = new MyClass();

Javascript可以通过嵌套闭包和多个“this”变量在不同的范围内浮动而变得有点毛茸茸。我更喜欢这样做:

var MyNoNewClass = function(){
    // I find this more explicit and less confusing
    var self = {}
    self.method = function(){}
    return self;
}

var myNoNewInstance = MyNoNewClass()

答案 2 :(得分:5)

引用了所有JavaScript内存,但不是传统意义上的。内存不是由内存地址引用,而是由字符串引用。在这段代码中:

var x = new someObj();

从该点开始,该对象由字符串“x”引用。 x不是指向堆上某些内存的指针。如果你为x分配了一个属性,那么:

x.someProp = 42;

然后someProp是内存中引用值42的字符串。因此,它允许您使用数组表示法通过它的字符串表示来访问它:

x["someProp"]++;

这也是变量可以保留任何值的原因,因为它们不需要大小。

当没有更多的字符串(也就是变量或属性名称)引用时,内存是用JavaScript收集的。当x被分配任何其他值时,将收集该对象。您可以将其设置为nullundefined或其他任何内容,并将收集内存。

也就是说,当浏览器或任何JavaScript引擎转向它时,它将被收集。

删除仅从对象中删除属性。从那时起,尝试访问该属性将返回undefined。在大多数情况下,以下两行代码是等效的:

x["someProp"] = undefined;
delete x.someProp;

编辑:好的,内部两条线不一样。删除操作符将从内存中删除“someProp”引用,而将其设置为undefined则不会。我认为。我在规范中找不到任何关于将变量或属性设置为undefined的内容,但我不认为这样做有什么特别之处。

需要注意的重要一点是,您将无法删除设置了某个标志的属性,但您可以将它们设置为null或undefined(如果它们没有被setter包装,甚至允许它发生)。

答案 3 :(得分:3)

在上下文(浏览器)之外,javascript完全能够通过垃圾回收来回收内存。回到现实垃圾收集结合DOM模型可能导致内存泄漏。

以下是一篇文章http://www.ibm.com/developerworks/web/library/wa-memleak/,您可以找到有关它的更多详细信息

答案 4 :(得分:2)

避免内存泄漏

  1. 确保删除所有事件处理程序,因此如果添加像鼠标按下事件处理程序,请确保在完成后将其删除
  2. 如果您向DOM添加元素,请在完成后删除它们
  3. 如果您有一个指向另一个对象的对象,则在完成该对象时删除该引用。
  4. 当你完成任何对象时,将其设置为null。
  5. 删除只是要从对象中删除属性。

答案 5 :(得分:1)

有一个delete。但是,实际需要它是罕见的。但它不像C ++删除。

JavaScript中的

delete将从对象中删除属性。对该属性的后续访问将返回undefined。我假设它可以在随后的垃圾收集中释放任何相关的内存。

答案 6 :(得分:1)

除非您要删除事件处理程序,否则请勿在JavaScript中使用delete。即使这样,我们也只是这样做,因为在旧版本的IE中存在与此实践相关的内存泄漏。道格拉斯·克罗克福德explains this非常好。在他的情况下,他甚至不使用delete。他只是将有问题的值设置为null

答案 7 :(得分:1)

来自MDC

  

delete运算符删除对象的属性或数组中指定索引处的元素。

我认为删除操作符仅在您想要从对象中删除属性时才有用。但是由于可能存在其引用的属性的其他引用,因此它不会真正用于GCed。如果你想要GCed的东西,你需要删除指向它的所有指针,并释放包含对它的引用的闭包(more info on the topic)。

答案 8 :(得分:1)

new从构造函数创建对象。 delete从对象中删除属性。这是两件截然不同的事情。

您不必删除自己创建的对象。 GC处理这个问题。

delete o.fuo.fu = undefined不同。试试这个:

var o = {};
alert(o.hasOwnProperty('fu')); // -> false
o.fu = undefined;
alert(o.hasOwnProperty('fu')); // -> true
delete o.fu;
alert(o.hasOwnProperty('fu')); // -> false

答案 9 :(得分:0)

Javascript中有delete,但请相信我:在C ++这样的东西中,方式delete不同。我建议您在使用Javascript之前不要考虑使用它。

垃圾收集工作,虽然它没有解决内存泄漏的问题。

答案 10 :(得分:0)

" new"关键字与内存无关。它的目的只是设置原型链。

// C++
Foo* foo = new Foo();                      // allocate and construct

// JS "sugar" using the new keyword
var foo = new Foo();                       // allocate and construct
assert(foo instanceof Foo);

// JS constructing objects without "new"
var foo = Object.create(Foo.prototype);    // allocate with prototype
Foo.call(foo);                             // construct
assert(foo instanceof Foo);

// construct Foo with missing prototype
var foo = {};                              // allocate without prototype
Foo.call(foo);                             // construct without prototype
assert(!(foo instanceof Foo));

// so the corollary operations in JS are
foo = {};
foo = null;

// where-as this is an error (or most certainly not what you want)
delete foo;

// and this is how delete is used
foo = {bar: 42};
assert(foo.bar === 42);
delete foo.bar;
assert(foo.bar === undefined);

// but by deleting a property, you remove the reference to the object
foo = {bar: {baz: 31}};
delete foo.bar;            // remove only reference to "bar" object
// JS GC will now take over

所以不,你不能删除对象。但是您可以删除对象的引用,这可能会触发GC删除对象。但是,当然,不能删除局部变量(和全局变量)。它们只是超出范围,取消引用任何相关对象,并可能释放内存,但前提是该对象未被返回或仍在其他地方引用。

重要的是要意识到因为JS不支持指针,所以GC可以是完美的。在任何时候,GC都可以简单地遍历整个对象组,并且可以看到"从任何范围内的功能,并保证它不会错过任何像周期等。

只要您在功能样式中使用JS并且不尝试构建将所有内容组合在一起的全局上帝对象,内存管理应该不是问题。