Может ли кто-нибудь поцарапать меня из-за характера исправления присвоения-нуля, используемого для предотвращения утечек памяти?
Мы все знакомы со следующей техникой, чтобы остановить циклическую ссылку между объектом DOM и объектом JS, чтобы предотвратить утечки памяти:
function foo() {
var ele = document.getElementById("someParagraphId");
ele.onclick = function() {
//some action here
};
ele = null;
}
Вопрос в том, почему вышеперечисленное сработает? Установка «ele» в ноль определенно остановит циклические ссылки, но разве это не помешает будущим ссылкам на «ele»?
function foo() {
var ele = document.getElementById("someParagraphId");
ele.onclick = function() {
console.log("accessing ele ... after set to null " + ele.onclick);
};
ele = null;
}
И все же слушатель события срабатывает. Он будет жаловаться, что объект "ele" является нулевым (что мы и ожидали).
Учитывая приведенное выше поведение, можем ли мы сделать вывод, что реализация движка Javascript будет содержать какую-то внутреннюю ссылку на прослушиватель событий, и именно эта ссылка вызывается при запуске события?
eventHandlerRef = //assignment to "ele.onclick" handler/listener;
Если бы существовала ссылка, подобная приведенной выше, не будет ли исправление присваивания нулю зависеть от реализации? Или это часть спецификации ECMAScript.
Насколько я понимаю, это исправление всегда было безопасным для разных браузеров. Я не сталкивался со многими примерами, в которых бы упоминались конкретные сведения об обнаружении / прослушивании типа браузера перед применением нулевого назначения.
=============== EDIT ==================
Я думаю, из-за того, как я изложил этот вопрос, возможно, невольно возникла непосредственная дискуссия из того, что я пытался донести. Пара понятий, на которые ссылаются:
дескрипторы объектов / ссылки на объекты ala:
var obj1, obj2;
obj1 = {foo: "bar"}; //obj1 points to the an area of the heap allocated
//for the object literal.
obj2 = obj1; //obj2 points to the same position in the heap
//as obj1.
//obj1 = null or
obj1 = {/*another obj literal*/} //the new object literal is created
//and allocated in some other part
//in the heap, and obj1 now points
//to the new location.
//obj2 is unaffected by obj1's re-assignment.
Выше не лежит мой зуд, и я сожалею, добавив строку:
console.log("accessing ele ... after set to null " + ele.onclick);
Сказанное выше делает этот вопрос закрытым. Я полностью ожидал, что ошибка будет выдана, как указано в исходном сообщении.
Мой зуд больше связан с контекстом ... по какой-то причине, по-моему, я продолжаю думать, что движок Javascript будет вызывать ele.onlick()
непосредственно при запуске события, и установка элемента в значение null сродни следующему поток:
var obj = {};
obj.method = function() {};
obj = null;
//error calling obj.method(), i.e., obj is null
Учитывая, что мы знаем в оригинальном посте, что обработчик событий все еще срабатывает после того, как ele был установлен в null, на мой взгляд, поток более похож на:
var obj = {};
obj.method = function() {};
var objRef = obj;
obj = null;
//The Javascript Engine calling objRef.method when event triggered.
Мой зуд сводится к вопросу, является ли описанное выше, как работает большинство реализаций Javascript, где какая-то внутренняя ссылка указывает на назначенный обработчик события, и эта внутренняя ссылка вызывается при запуске события?
Или по-другому, что мешает реализации Javascript Engine вызывать ele.onclick()
напрямую (оставляя в стороне проблемы дизайна и архитектуры)?
Возможно, мои мыслительные процессы работают по-другому, но никто больше не взглянул во второй раз, когда впервые столкнулся с исправлением присваивания-нуля, где ссылка на элемент была нулевой, и все же код для обработчика все еще был казнен?