Удаление объектов в JavaScript
Я немного запутался с оператором JavaScript delete
. Возьмите следующий фрагмент кода:
var obj = {
helloText: "Hello World!"
};
var foo = obj;
delete obj;
После выполнения этой части кода obj
есть null
, но foo
все равно относится к объекту, точно как obj
. Я предполагаю, что этот объект является тем же объектом, на который указывает foo
.
Это меня смущает, потому что я ожидал, что запись delete obj
удалит объект, на который obj
указывал в памяти, а не только переменную obj
.
Это потому, что JavaScript Garbage Collector работает на основе сохранения/выпуска, так что если бы у меня не было других переменных, указывающих на объект, оно было бы удалено из памяти?
(Кстати, мое тестирование было выполнено в Safari 4.)
Ответы
Ответ 1
Оператор delete удаляет только ссылку, а не сам объект. Если бы он удалил сам объект, другие оставшиеся ссылки были бы свисающими, например, С++ delete. (И доступ к одному из них приведет к сбою. Для того, чтобы все они обменивались с нулем, это означало бы наличие дополнительной работы при удалении или дополнительной памяти для каждого объекта.)
Поскольку Javascript - сбор мусора, вам не нужно удалять объекты сами - они будут удалены, когда больше не будет ссылок на них.
Может быть полезно удалить ссылки на объект, если вы закончили с ними, потому что это дает сборщику мусора дополнительную информацию о том, что можно вернуть. Если ссылки остаются на большом объекте, это может привести к его невосстановлению - даже если остальная часть вашей программы фактически не использует этот объект.
Ответ 2
Команда 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.)
Ответ 3
"переменные, объявленные неявно", являются свойствами глобального объекта, поэтому удаление работает над ними, как будто оно работает с любым свойством. Переменные, объявленные с помощью var, нерушимы.
Ответ 4
Исходя из документации Mozilla: "Вы можете использовать оператор delete для удаления переменных, объявленных неявно, но не объявленных с помощью оператора var".
Вот ссылка: https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference:Operators:Special_Operators:delete_Operator
Ответ 5
на основе ответа @Guffa. Я нашел, что для меня работает следующий метод:
var obj = {
helloText: "Hello World!"
};
obj = null;
delete obj;
Сначала задав объект obj null
, вы удалили всю ссылку на него, затем вы можете полностью удалить его.
Я не тестировал его в другом браузере, но это работает в phonegap 1.7.0
Ответ 6
delete
не используется для удаления объекта в Java Script.
delete
используется для удаления object key
в вашем случае
var obj = { helloText: "Hello World!" };
var foo = obj;
delete obj;
объект не удален проверить объект все еще принимать те же значения удалить использование:
delete obj.helloText
и затем проверьте obj, foo
, оба являются пустым объектом.
Ответ 7
Помимо вопросов GC, для производительности следует учитывать оптимизацию, которую браузер может выполнять в фоновом режиме →
http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/
Кажется, что было бы лучше сбросить ссылку, чем удалить ее, поскольку это может изменить класс за кадром, используемый Chrome.
Ответ 8
Просто нашел jsperf, который может показаться интересным в свете этого вопроса. (было бы удобно держать его вокруг, чтобы завершить изображение)
Он сравнивает удалять, устанавливая null и устанавливая undefined.
Но имейте в виду, что он проверяет случай, когда вы удаляете/устанавливаете свойство много раз.
Ответ 9
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 api...
el.parent.removeChild(el._host);
Ответ 10
Я наткнулся на эту статью в своем поиске этого же ответа. То, что я закончил, - это просто вывести obj.pop()
все сохраненные значения/объекты в моем объекте, чтобы я мог повторно использовать объект. Не уверен, что это плохая практика или нет. Этот метод оказался полезным для тестирования моего кода в инструментах Chrome Dev или в FireFox Web Console.
Ответ 11
Это работа для меня, хотя это не очень хорошая практика. Он просто удаляет все связанные элементы, к которым принадлежит объект.
for (element in homeService) {
delete homeService[element];
}
Ответ 12
Установка переменной в null
позволяет обрывать любые ссылки на объекты во всех браузерах, включая круговые ссылки между элементами DOM и областями Javascript. Используя команду delete
, мы отмечаем объекты, подлежащие очистке при следующем запуске коллекции Garbage, но если есть несколько переменных, ссылающихся на один и тот же объект, удаление одной переменной НЕ освобождает объект, он просто удалит связь между эту переменную и объект. И при следующем запуске коллекции мусора будет очищена только переменная.