326

Я немного смущен оператором JavaScript delete. Рассмотрим следующий фрагмент кода:Удаление объектов в JavaScript

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

var foo = obj; 

delete obj; 

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

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

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

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

+7

Для справки. https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/delete_Operator –

+0

Полная статья по ключевому слову delete http://webcache.googleusercontent.com/search?q=cache:auElwuFsub0J:perfectionkills.com/ понимание-delete/+ delete + javascript & cd = 2 & hl = en & ct = clnk & client = safari –

+2

Ссылка выше должна быть: http://perfectionkills.com/understanding-delete – johnmdonahue

ответ

412

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

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

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

+13

Ключевое слово 'delete' работает только для свойств объекта, а не для переменных. http://perfectionkills.com/understanding-delete/ – AlexJM

+1

@AlexJM Да, следующий ответ Гуффа (и его комментарии) обсуждает это в деталях. –

+1

Свойством объекта может быть другой объект. Например; 'var obj = {a: {}}; delete obj.a; ' – AlexJM

147

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)

+33

Если это выполняется в глобальной области видимости, ваша переменная 'x' становится просто свойство на глобальном объекте 'window' и' delete x; 'действительно действительно удаляет переменную' x'. –

+17

@crescentfresh: Это свойство, если оно неявно объявлено. Если он явно объявлен как в примере, это глобальная переменная и не может быть удалена. – Guffa

+1

Почему downvote? Если вы не объясните, что вы считаете неправильным *, он не сможет улучшить ответ. – Guffa

47

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

+1

Хороший совет, я никогда не рассматривал это раньше ... – jason

+37

Я никогда не понимал, что вар был настолько задир. – Gavin

+0

Это замечательный момент, и JS получил. Люди привыкают к удалению оконных варов, а затем задаются вопросом, почему они не могут сделать то же самое с локальными переменными. – welbornio

1

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 всегда возвращает истину в 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 

если ваша потребность использовать хост-объект с хост-апи ...

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

Большое спасибо! –

7

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

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

obj = null; 

delete obj; 

Установив OBJ в null первый, вы удалили все ссылки на него, то вы можете удалить его полностью.

я не проверял его на другом браузере, но это работает в PhoneGap 1.7.0

+29

umm .. разве вы не просто удаляете «нуль» здесь? – lambinator

+0

Возможно, я ошибаюсь, но [ответы здесь] (http://stackoverflow.com/questions/742623/deleting-objects-in-javascript) показывают, что установка в значение null не будет делать ничего полезного. –

+0

Я думаю, что здесь произошло 2 вещи: 1. потеря ссылки на нуль, 2. также потеряна ссылка на объект, официально ссылающийся на obj. Так что, скорее всего, это будет означать GC, потому что в этом нет никакой ссылки. – Cardin

2

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

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

оказывается, это может быть лучше обнулить ссылку, чем удалить его, как это может изменить закулисный «класс» использует Chrome.

0

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

0

Установка переменной в null позволяет обрывать любые ссылки на объекты во всех браузерах, включая круговые ссылки между элементами DOM и областями Javascript. Используя команду delete, мы отмечаем объекты, подлежащие очистке при следующем запуске коллекции мусора, но если есть несколько переменных, ссылающихся на один и тот же объект, удаление одной переменной НЕ освободит объект, он просто удалит связь между этой переменной и объект. И при следующем запуске коллекции мусора будет очищена только переменная.

2

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

Он сравнивает удаление, установка нуля и установка неопределенную.

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

4

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

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

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

объект не удаляется проверка OBJ все еще принимают одинаковые значения удалить использование:

delete obj.helloText 

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

0

Эта работа для меня, хотя это не очень хорошая практика. Он просто удаляет весь связанный с ним элемент .

for (element in homeService) { 
      delete homeService[element]; 
Смежные вопросы