Ответ 1
var component = new Component();
component = null; // delete this at next garbage collection
Исходя из С++, мне трудно понять, что каждый раз, когда я вызываю new
, я вызываю delete
. В JavaScript я иногда вызываю new
в моем коде, но (надеясь) функция сбора мусора в браузере позаботится о беспорядке для меня.
Мне это не нравится - есть ли метод delete
в JavaScript и как я его использую в С++?
Спасибо.
var component = new Component();
component = null; // delete this at next garbage collection
Кстати, ключевое слово "новое" на самом деле не нужно в javascript и не имеет ничего (непосредственно) делать с распределением памяти. Все "новые" - это передать новый пустой объект с именем "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();
Javascript может выглядеть как волосатый с вложенными замыканиями и несколькими переменными "this", плавающими в разных областях. Я предпочитаю делать это следующим образом:
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"]++;
Кроме того, переменные могут сохранять любое значение, так как они не нуждаются в размере.
Память собрана в JavaScript, эффективно, когда на нее ссылаются больше строк (так называемых переменных или имен свойств). Этот объект будет собран, когда x присваивается любое другое значение. Вы можете установить его на null
, undefined
или что-нибудь еще, и эта память будет собрана.
То есть, он будет собран, когда браузер или какой-либо движок JavaScript приблизится к нему.
Удалить удаляет только объекты из объектов. С этого момента попытка доступа к этому свойству вернет undefined
. По большей части следующие две строки кода эквивалентны:
x["someProp"] = undefined;
delete x.someProp;
Изменить: Хорошо, внутренне две линии не совпадают. Оператор удаления удаляет ссылку "someProp" из памяти, а установка ее на undefined - нет. Я думаю. Я не могу найти ничего в спецификации о настройке переменной или свойства на undefined, но я не думаю, что это делает что-то особенное.
Важно отметить, что вы не сможете удалять свойства с определенным набором флагов, но вы можете установить их в null или undefined (если они не обернуты сеттером и даже позволяют это произойдет).
Вне контекста (браузера) javascript полностью способен восстанавливать память через сбор мусора. Возвращение к сборке мусора реальности в сочетании с моделью DOM может привести к утечкам памяти.
Вот одна статья http://www.ibm.com/developerworks/web/library/wa-memleak/ вы можете найти более подробную информацию об этом
Чтобы избежать утечек памяти
удаляет только что удалить свойство из объекта.
Существует delete
. Однако настоящая потребность в ней будет редкими. Это не похоже на С++ delete.
delete
в JavaScript удалит свойство из объекта. Последующие обращения этого свойства вернут undefined. Я предполагаю, что он сможет освободить любую связанную память при последующих сборах мусора.
Не используйте delete
в JavaScript, если вы не удаляете обработчики событий. Даже тогда мы делаем это только потому, что в более старых версиях IE существует утечка памяти, связанная с этой практикой. Douglas Crockford объясняет это довольно хорошо. В его случае он даже не использует delete
. Он просто задает значения, о которых идет речь, null
.
Из MDC:
Оператор delete удаляет свойство объекта или элемент с указанным индексом в массиве.
Оператор delete, на мой взгляд, полезен только тогда, когда вы хотите удалить свойство из объекта. Но поскольку могут быть другие ссылки на свойство, на которое он ссылается, он не будет действительно GCed. Если вы хотите, чтобы что-то было GCed, вам нужно удалить все указатели, указывающие на него, а также освободить блокировки, содержащие ссылки на него (дополнительная информация по теме).
new
создает объекты из конструктора. delete
удаляет свойства объекта. Это две разные вещи.
Вам не нужно удалять созданные объекты. GC заботится об этом.
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
, но поверьте мне: способ отличается от delete
чем-то вроде С++. Я рекомендую вам даже не думать об использовании этого, пока вам не станет удобнее Javascript.
Работа по сборке мусора, хотя и не устраняет проблему утечек памяти.
Ключевое слово "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 в функциональном стиле и не пытаетесь создать глобальные объекты-боги, которые связывают все вместе, управление памятью должно быть не проблемой.