2013-06-28 2 views
4

Если я сделать следующее (в глобальном масштабе):Javascript: Что происходит с объектами, у которых нет имени?

var myObject = {name: "Bob"}; 

у меня есть способ, чтобы указать на этот объект в памяти (то есть строка идентификатор «MyObject)». Я могу открыть консоль и введите: myObject.name и консоль ответит:

"Bob" 

Теперь, если я просто наберите:

{name: "Jane"}; 

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

Редактировать: Некоторые люди говорят, что он просто получит мусор.

Так как об этом примере:

var MyObject = function(){ 
    $("button").click(this.alert); 
} 

MyObject.prototype.alert = function(){ 
    alert("I heard that!") 
} 

new MyObject(); 

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

+0

Неа. Объект создан и собран мусор. Точно так же, как '' use strict '; 'string. Я думаю, что некоторые JS-движки могут даже избежать создания – MaxArt

+0

Кто-то еще спросил это, но удалил свой комментарий.Является ли ваш первый пример определенно даже определяющим объект, который вы считаете, или это просто блок, метка и строка? –

+1

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

ответ

2

Короткий ответ no, объект не хранится в памяти, где вы не можете добраться. Бит жизнь живая: правда немного сложнее, но не намного, если вы поймете основы.

Update:
В ответ на ваше обновление: вы правы, в некотором смысле. Обратный вызов является ссылкой на MyObject.prototype.alert, к которому вы обращались с использованием this.alert, но этот функциональный объект ссылается на прототип конструкторов и не может быть GC'ed в любом случае. Экземпляр сам не участвует в самой функции alert, поэтому он может быть безопасным для GC.

Думай об этом, как это:

MyConstructor.prototype.alert = 0x000123;//some memory address 
    || 
    \/ 
0x00= [object Function]; 

Сама функция объект непосредственно не привязывается ни к чему, она плавает там в памяти, и в настоящее время ссылается на прототип. При создании экземпляра:

new MyConstructor().alert; 

решается следующим образом:

[new MyConstructor instance] allocated at e.g 0x000321 
    || 
    \\ 
    \=>[alert] check for alert @instance -> not found 
      \\ 
      \=> check prototype, yield 0x00<-- memory address, return this value 

Так при выполнении оператора:

$("button").click(this.alert); 

this.alert это выражение, которое разрешен к 0x000123. Другими словами, метод jQ click (объект функции) получает только адрес памяти объекта функции alert. Экземпляр или конструктор вообще не задействованы.Вот почему или контекст вызова могут меняться в зависимости от того, как и где вызывается функция. see here for more on ad-hoc context determination

Я даже ты один лучше:

/*assume your code is here*/ 
new MyConstructor().alert = function(){ alert('I am deaf');}; 
MyConstructor.prototype.alert = 'foo'; 
$('#button').click(); 

Угадайте, что событие щелчка оповещения «Я слышал, что» все то же самое, прототип даже не участвует, пусть один экземпляр.
Если MyConstructor должны были выйти из области видимости, событие click все равно будет работать нормально, поскольку GC все еще видит ссылку на объект функции оповещения, который еще не выходит за пределы области видимости. все остальное доступно для GC'ing, хотя ...


JS сборщик мусора (GC) является флагом и салфетки GC. Когда JS-двигатель встречает ваш оператор, он делает выделяет память, необходимую для хранения вашего объекта. Когда будет достигнут следующий оператор, этот объект, вероятно, все еще будет в памяти.
Время от времени GC X проверяет все объекты, которые он видит в памяти, и пытается найти все ссылки на этот объект, который все еще доступен. Когда он встречается с литералом объекта, который был только что создан в этом выражении, но ссылка не была назначена, объект помечен для сбора мусора.
В следующий раз, когда GC узнает о своем бизнесе с помощью объекта подмеченного объекта, этот объект будет удален из памяти.

Конечно, это относится не только к всем двигателям. предположим, что ваше заявление было написано в IIFE, что возвратила функция:

var foo = function() 
{ 
    {name: 'bar'}; 
    return function() 
    { 
     return 'foobar'; 
    }; 
}()); 

Некоторые двигатели просто держать всю сферу IIFE в памяти, и только освободить память для этой сферы, когда значение возврата из IIFE выходит за пределы области действия (отмечен для GC). Другие двигатели, такие как V8 в прошлый раз, когда я проверял, фактически будут помечать те объекты/vars внешней области, на которые не ссылается его возвращаемое значение.
Хотя, подумайте об этом, это может не относиться к этому случаю, потому что GC может даже нанести удар даже до возвращения IIFE ... Но в целом это просто nit-picking.

Там также вопрос о том, логических ИЛИ, чтобы рассмотреть следующие вопросы:

var name = (mayNotExist || {name:'default'}).name; 

В этом случае, если mayNotExistли существует, литерал объект никогда не будет даже создано, благодаря оценке короткого замыкания JS в выражениях ,

Несколько ссылок по этому вопросу:

+0

Спасибо за самый полный ответ. –

5

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

+2

Мне нравится думать, что он сбежал и живет на ягненок – Yatrix

+2

@ Ятрикс Я думаю, что это «на ламе», но «живое на ягненке» звучит вкуснее! –

+0

@MattHarrison Хе-хе. Я никогда не был на ламе, но если я когда-либо, надеюсь, у меня есть ягненок возьмите с собой. – Yatrix