Подтвердить что ты не робот

Новое ключевое слово JavaScript и управление памятью

Исходя из С++, мне трудно понять, что каждый раз, когда я вызываю new, я вызываю delete. В JavaScript я иногда вызываю new в моем коде, но (надеясь) функция сбора мусора в браузере позаботится о беспорядке для меня.

Мне это не нравится - есть ли метод delete в JavaScript и как я его использую в С++?

Спасибо.

4b9b3361

Ответ 1

var component = new Component();
component = null; // delete this at next garbage collection

Ответ 2

Кстати, ключевое слово "новое" на самом деле не нужно в 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()

Ответ 3

Вся память 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 (если они не обернуты сеттером и даже позволяют это произойдет).

Ответ 4

Вне контекста (браузера) javascript полностью способен восстанавливать память через сбор мусора. Возвращение к сборке мусора реальности в сочетании с моделью DOM может привести к утечкам памяти.

Вот одна статья http://www.ibm.com/developerworks/web/library/wa-memleak/ вы можете найти более подробную информацию об этом

Ответ 5

Чтобы избежать утечек памяти

  • Убедитесь, что вы удалили все обработчики событий, поэтому, если вы добавили как обработчик событий мыши, убедитесь, что вы удалили его, когда закончили
  • если вы добавите элементы в DOM, удалите их, когда закончите
  • Если у вас есть объект, указывающий на другой объект, удалите ссылку, когда объект сделан.
  • когда вы закончите с любым объектом, установите его равным null.

удаляет только что удалить свойство из объекта.

Ответ 6

Существует delete. Однако настоящая потребность в ней будет редкими. Это не похоже на С++ delete.

delete в JavaScript удалит свойство из объекта. Последующие обращения этого свойства вернут undefined. Я предполагаю, что он сможет освободить любую связанную память при последующих сборах мусора.

Ответ 7

Не используйте delete в JavaScript, если вы не удаляете обработчики событий. Даже тогда мы делаем это только потому, что в более старых версиях IE существует утечка памяти, связанная с этой практикой. Douglas Crockford объясняет это довольно хорошо. В его случае он даже не использует delete. Он просто задает значения, о которых идет речь, null.

Ответ 8

Из MDC:

Оператор delete удаляет свойство объекта или элемент с указанным индексом в массиве.

Оператор delete, на мой взгляд, полезен только тогда, когда вы хотите удалить свойство из объекта. Но поскольку могут быть другие ссылки на свойство, на которое он ссылается, он не будет действительно GCed. Если вы хотите, чтобы что-то было GCed, вам нужно удалить все указатели, указывающие на него, а также освободить блокировки, содержащие ссылки на него (дополнительная информация по теме).

Ответ 9

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

Ответ 10

В Javascript есть delete, но поверьте мне: способ отличается от delete чем-то вроде С++. Я рекомендую вам даже не думать об использовании этого, пока вам не станет удобнее Javascript.

Работа по сборке мусора, хотя и не устраняет проблему утечек памяти.

Ответ 11

Ключевое слово "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 в функциональном стиле и не пытаетесь создать глобальные объекты-боги, которые связывают все вместе, управление памятью должно быть не проблемой.