Удаление объектов в JavaScript - PullRequest
347 голосов
/ 13 апреля 2009

Я немного запутался с оператором JavaScript delete. Возьмите следующий кусок кода:

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

var foo = obj;

delete obj;

После того, как этот фрагмент кода был выполнен, obj равен null, но foo по-прежнему ссылается на объект в точности как obj. Я предполагаю, что этот объект является тем же объектом, на который foo указал.

Это смущает меня, потому что я ожидал, что запись delete obj удалит объект, на который obj указывает в памяти, а не только переменную obj.

Это потому, что сборщик мусора в JavaScript работает на основе сохранения / выпуска, поэтому, если бы у меня не было других переменных, указывающих на объект, он был бы был бы удален из памяти?

(Кстати, мое тестирование проводилось в Safari 4.)

Ответы [ 12 ]

436 голосов
/ 13 апреля 2009

Оператор удаления удаляет только ссылку, но не сам объект. Если бы он действительно удалил сам объект, другие оставшиеся ссылки были бы висячими, как удаление C ++. (И доступ к одному из них приведет к сбою. Чтобы все они стали пустыми, это означало бы дополнительную работу при удалении или дополнительную память для каждого объекта.)

Поскольку Javascript является сборщиком мусора, вам не нужно удалять сами объекты - они будут удалены, когда уже нет возможности ссылаться на них.

Может быть полезно удалить ссылки на объект, если вы закончили с ними, потому что это дает сборщику мусора больше информации о том, что можно восстановить. Если ссылки остаются на большой объект, это может привести к тому, что он не будет восстановлен, даже если остальная часть вашей программы фактически не использует этот объект.

155 голосов
/ 13 апреля 2009

Команда 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.)

54 голосов
/ 14 июля 2011

«переменные, объявленные неявно» - это свойства глобального объекта, поэтому delete работает с ними так же, как и с любым свойством. Переменные, объявленные с помощью var, неразрушимы.

23 голосов
/ 13 апреля 2009

Исходя из документации Mozilla: «Вы можете использовать оператор удаления для удаления переменных, объявленных неявно, но не тех, которые объявлены с помощью оператора var.»

Вот ссылка: https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Operators:Special_Operators:delete_Operator

6 голосов
/ 21 июня 2012

на основании ответа @Guffa. Я нашел следующий метод работает для меня:

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

obj = null;

delete obj;

Установив для obj значение null, сначала вы удалили все ссылки на него, а затем можете полностью удалить его.

Я не тестировал его в другом браузере, но это работает в phonegap 1.7.0

4 голосов
/ 15 апреля 2016

delete не используется для удаления объекта в Java Script.

delete используется для удаления object key в вашем случае

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

объект не удален, проверка obj по-прежнему принимает те же значения удалить использование:

delete obj.helloText

и затем проверьте obj, foo, оба являются пустым объектом.

2 голосов
/ 12 февраля 2015

Только что нашел jsperf , который может показаться вам интересным в свете этого вопроса. (может быть удобно держать его рядом, чтобы завершить картину)

Сравнивает удалить , настройку null и настройку undefined .

Но имейте в виду, что он проверяет случай, когда вы удаляете / устанавливаете свойство много раз.

2 голосов
/ 08 апреля 2013

Помимо вопросов GC, для повышения производительности следует учитывать оптимизацию, которую браузер может выполнять в фоновом режиме ->

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

Похоже, что может быть лучше обнулить ссылку, чем удалить ее, поскольку это может изменить скрытый "класс", который использует Chrome.

1 голос
/ 04 августа 2013

Я наткнулся на эту статью в поиске этого же ответа. В итоге я просто извлек obj.pop() все сохраненные значения / объекты в моем объекте, чтобы я мог повторно использовать этот объект. Не уверен, если это плохая практика или нет. Этот метод пригодился для тестирования моего кода с помощью инструментов Chrome Dev или веб-консоли FireFox.

1 голос
/ 18 ноября 2011

В IE 5-8 есть ошибка, когда при использовании delete для свойств хост-объекта (Window, Global, DOM и т. Д.) Выдается 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 всегда будет возвращать true в IE.

Если вам действительно нужно, чтобы имущество действительно исчезло ...

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

если вам нужно использовать объект host с host api ...

el.parent.removeChild(el._host);
...