作为一个C++开发者,我会下意识地在每次调用new
时也调用delete
。但在JavaScript中,尽管偶尔会使用new
,我还是希望(希望)浏览器的垃圾回收功能能够自动处理这些。
我不太喜欢这种方式 - 在JavaScript中是否有delete
方法,并且与C++中的使用方式有何不同?
谢谢。
作为一个C++开发者,我会下意识地在每次调用new
时也调用delete
。但在JavaScript中,尽管偶尔会使用new
,我还是希望(希望)浏览器的垃圾回收功能能够自动处理这些。
我不太喜欢这种方式 - 在JavaScript中是否有delete
方法,并且与C++中的使用方式有何不同?
谢谢。
var component = new Component();
component = null; // delete this at next garbage collection
new Component().init();
这会有什么性能后果吗? - Danimt其实,在JavaScript中,“new”关键字并不是必需的,也与分配内存无关。所有“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();
嵌套闭包和多个“this”变量在不同的作用域中流动,使Javascript变得有点复杂。我更喜欢这种方式:
var MyNoNewClass = function(){
// I find this more explicit and less confusing
var self = {}
self.method = function(){}
return self;
}
var myNoNewInstance = MyNoNewClass()
所有的JavaScript内存都是以参考方式进行的,但不是传统意义上的参考。内存不是通过内存地址引用,而是通过字符串引用。在这段代码中:
var x = new someObj();
从那时起,该对象由字符串“x”引用。此时,x不是指向堆上某个内存的指针。如果您给x分配了一个属性,则:
x.someProp = 42;
那么,someProp是一个字符串,它在内存中引用值42。因此,您可以使用数组表示法通过其字符串表示访问它:
x["someProp"]++;
x["someProp"] = undefined;
delete x.someProp;
编辑:好的,实际上这两行代码在内部并不相同。delete操作符会从内存中删除“someProp”引用,而将其设置为undefined则不会。我想是这样的。我在规范中找不到有关将变量或属性设置为undefined的任何内容,但我认为这样做并没有什么特殊的作用。
需要注意的重要事项是,您将无法删除具有某个标志设置的属性,但是您可以将它们设置为null或undefined(如果它们未被setter包装,甚至允许这种情况发生)。
在浏览器之外,JavaScript 可以通过垃圾回收完全恢复内存。但是,在实际应用中,与 DOM 模型结合使用的垃圾回收可能会导致内存泄漏。
这里有一篇文章http://www.ibm.com/developerworks/web/library/wa-memleak/,你可以在其中找到更多详细信息。
"delete"仅会从对象中删除属性。
new
从构造函数创建对象。delete
从对象中删除属性。这是两个非常不同的事情。
您不必删除已创建的对象。垃圾回收器会处理此问题。
delete o.fu
与 o.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
在JavaScript中有一个delete
。然而,实际需要它的情况很少。它不像C++的delete。
delete
会从对象中删除一个属性。随后访问该属性将返回undefined。我认为它能够在随后的垃圾回收中释放任何相关的内存。
在 JavaScript 中,除非你要删除事件处理程序,否则不要使用 delete
。即使是这样,我们也只是因为旧版本的 IE 存在与此实践相关的内存泄漏问题。Douglas Crockford 很好地解释了 这一点。在他的情况下,他甚至不使用 delete
。他只是将相关的值设置为 null
。
来自MDC:
delete 运算符可以删除对象的属性或数组中指定索引处的元素。
在我看来,delete 运算符仅在您想要从对象中删除属性时才有用。但是,由于可能存在对其引用的其他引用,因此它不会真正被垃圾回收。如果您希望某些内容被垃圾回收,您需要删除所有指向它的指针,并释放包含对其引用的闭包(有关该主题的更多信息)。
"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,并且不尝试构建将所有内容绑定在一起的全局对象,内存管理就不应该成为问题。