在JavaScript中删除对象

我对JavaScript的delete操作符有点困惑。以下面这段代码为例:

var obj = {
helloText: "Hello World!"
};


var foo = obj;


delete obj;

在这段代码执行之后,objnull,但是foo仍然引用一个与obj完全相同的对象。我猜这个对象就是foo指向的那个对象。

这让我很困惑,因为我以为写delete obj会删除obj在内存中指向的对象——而不仅仅是变量obj

这是因为JavaScript的垃圾收集器是在保留/释放的基础上工作的,所以如果我没有任何其他变量指向对象,它将从内存中删除?

(顺便说一下,我的测试是在Safari 4中完成的。)

439415 次浏览

delete命令对普通变量没有作用,只对属性有作用。在delete命令之后,属性没有值null,它根本不存在。

如果属性是对象引用,delete命令删除属性,但不删除对象。如果该对象没有其他引用,则垃圾收集器将处理该对象。

例子:

var x = new Object();
x.y = 42;


alert(x.y); // shows '42'


delete x; // no effect
alert(x.y); // still shows '42'


delete x.y; // deletes the property
alert(x.y); // shows 'undefined'

(在Firefox中测试。)

来自Mozilla文档,“您可以使用delete操作符删除隐式声明的变量,但不能删除用var语句声明的变量。”

下面是链接:https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Operators:Special_Operators:delete_Operator

delete操作符只删除引用,从不删除对象本身。如果它确实删除了对象本身,其他剩余的引用将悬空,就像c++删除一样。(访问其中一个会导致崩溃。将它们全部变为null意味着在删除每个对象时需要额外的工作或额外的内存。)

因为Javascript是垃圾收集的,所以你不需要删除对象本身——当没有办法再引用它们时,它们就会被删除。

如果您已经完成了对对象的引用,那么删除它们可能会很有用,因为这为垃圾收集器提供了更多关于可以回收的内容的信息。如果对大对象的引用仍然存在,则可能导致该对象不可回收——即使程序的其余部分实际上并不使用该对象。

“隐式声明的变量”是全局对象的属性,所以删除对它们的作用就像对任何属性一样。用var声明的变量是不可破坏的。

ie5到ie8有一个错误,在主机对象(Window, Global, DOM等)的属性上使用delete会抛出TypeError“对象不支持此操作”。

var el=document.getElementById("anElementId");
el.foo = {bar:"baz"};
try{
delete el.foo;
}catch(){
//alert("Curses, drats and double double damn!");
el.foo=undefined; // a work around
}

稍后,如果你需要检查属性在哪里具有完整的含义,请使用el.foo !== undefined,因为"foo" in el 在IE中总是返回true。

如果你真的想让房子消失……

function hostProxy(host){
if(host===null || host===undefined) return host;
if(!"_hostProxy" in host){
host._hostproxy={_host:host,prototype:host};
}
return host._hostproxy;
}
var el=hostProxy(document.getElementById("anElementId"));
el.foo = {bar:"baz"};


delete el.foo; // removing property if a non-host object

如果你需要使用主机api的主机对象…

el.parent.removeChild(el._host);

除了GC问题之外,对于性能,应该考虑浏览器可能在后台执行的优化—>

http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/

这似乎是更好的空引用比删除它,因为这可能会改变幕后的'类' Chrome使用。

在寻找同样的答案时,我偶然发现了这篇文章。我最终所做的只是在对象中弹出obj.pop()所有存储的值/对象,以便我可以重用该对象。不知道这是不是不好的做法。这个技巧在我用Chrome Dev工具或FireFox Web Console测试代码时派上了用场。

将变量设置为null确保打破所有浏览器中对对象的任何引用,包括DOM元素和Javascript作用域之间的循环引用。通过使用delete命令,我们在下一次运行垃圾收集时标记要清除的对象,但如果有多个变量引用同一个对象,删除单个变量不会释放该对象,它只会删除该变量和该对象之间的链接。在下一次运行垃圾收集时,只会清理变量。

刚刚发现了一个jsperf,你可能会认为在这个问题上很有趣。(把它放在周围可以方便地完成图片)

它比较了delete, setting null和setting undefined

但请记住,当您多次删除/设置属性时,它会测试情况。

在java Script中,delete不用于删除对象。

在你的例子中,delete用于移除object key

var obj = { helloText: "Hello World!" };
var foo = obj;
delete obj;

对象未被删除检查obj仍然采用相同的值 delete用法:

delete obj.helloText

然后检查obj, foo,两者都是空对象。

这对我来说很有用,尽管这不是一个好的练习。它简单地删除所有的 对象所属的关联元素。< / p >
 for (element in homeService) {
delete homeService[element];
}

delete操作符从数组中删除对象、对象的属性或元素。操作符还可以删除未使用var语句声明的变量。 在下面的例子中,'fruits'是一个声明为var的数组,并被删除(真的吗??)

delete objectName
delete objectName.property
delete objectName[index]
delete property // The command acts  only within a with statement.


var fruits = new Array("Orange", "Apple", "Banana", "Chery");
var newParagraph = document.createElement("p");
var newText = document.createTextNode("Fruits List : " + fruits);
newParagraph.appendChild(newText);
document.body.appendChild(newParagraph);
//Delete the array object.
delete fruits;
var newParagraph1 = document.createElement("p");
var newText1 = document.createTextNode("Display the Fruits after delete the array object - Fruits List : "+ fruits;);
newParagraph1.appendChild(newText1);
document.body.appendChild(newParagraph1);

https://www.w3resource.com/javascript/operators/delete.php

我们有多种方法来删除Object属性。

箭头功能:我们还可以使用箭头函数从对象中删除属性,这是一个一行程序解决方案。

const obj = {
'first': 'one',
'second': 'two',
'third': 'three'
}


const fn = (key, { [key]: deletedKey, ...others }) => others;


console.log(fn('first', obj))        // { 'second': 'two', 'third': 'three' }

减少的方法:在javascript中,我们可以使用reduce方法从原始对象中删除特定的属性。

const obj = {
'first': 'one',
'second': 'two',
'third': 'three'
}


const exceptSecond = Object.keys(obj).reduce((acc, key) => {
if (key !== 'second') {
acc[key] = obj[key]
}
return acc
}, {})


console.log(exceptSecond)    // { 'first': 'one', 'third': 'three' }

删除:这是一种简单的删除方法。

delete obj.first;
// Or
delete obj['first'];

使用unset,省略,Pic方法从“loadash"自由:

    import { unset } from 'lodash'




const obj = {
'first': 'one',
'second': 'two',
'third': 'three'
}


unset(obj, 'third')        // true


console.log(obj)        // { 'first': 'one', 'second': 'two' }


// Using omit
import { omit } from 'lodash'
const obj1 = {
'first': 'one',
'second': 'two',
'third': 'three'
}


omit(obj1, [ 'first', 'second' ])


console.log(obj1)

反射删除属性:这是ES6中引入的新的内置对象。现在可以通过调用这个Refect对象的deleted property()函数来删除对象属性。

这个函数等价于我们在第一个方法中讨论的delete操作符。

const someObject = {
'first': 'one',
'second': 'two',
'third': 'three'
}


Reflect.deleteProperty(someObject, 'second')


console.log(someObject)        //  { 'first': 'one', 'third': 'three' }

如果你想根据对象的值删除它,可以这样做:

Object.keys(obj).forEach((key) => {
if (obj[key] === "Hello World!") {
delete obj[key];
}
});

但是删除对象并不是一个好主意。因此,将其设置为undefined,以便在将其传递给参数时。它不会显示出来。无需删除。

Object.keys(obj).forEach((key) => {
if (obj[key] === "Hello World!") {
obj[key] = undefined;
}
});