21.02.2018, 19:15
|
Интересующийся
|
|
Регистрация: 09.02.2018
Сообщений: 27
|
|
Задача про img и события load/error
Есть задача: https://learn.javascript.ru/task/load-img-callback
В решении этой задачи есть строка с кодом:
for (var i = 0; i < sources.length; i++) {
var img = document.createElement('img');
img.onload = img.onerror = onLoad;
img.src = sources[i];
}
Как я понимаю, переменная, объявленная через var, будет одна на все итерации цикла for. Получается, что каждая новая итерация цикла будет перезаписывать переменную img новыми данными, но в данной ситуации интерпретатор для каждой итерации запоминает img как отдельную новую переменную и запоминает её в памяти отдельно. Получается, что каждая итерация не переприсваивает переменную img, её обработчики и src, а создает новую. На выходе мы имеем 3 разных img со своим атрибутом src и своими обработчиками. Почему так происходит? Это из-за атрибута src?
|
|
21.02.2018, 19:27
|
|
Профессор
|
|
Регистрация: 01.12.2016
Сообщений: 3,650
|
|
создает новую, убивая старую (пиф паф)
|
|
21.02.2018, 19:31
|
Интересующийся
|
|
Регистрация: 09.02.2018
Сообщений: 27
|
|
Что-то мне отладчик другое говорит
|
|
21.02.2018, 19:33
|
|
Профессор
|
|
Регистрация: 01.12.2016
Сообщений: 3,650
|
|
напишите в консоле img и посмотрите что в ней.
|
|
21.02.2018, 20:10
|
Интересующийся
|
|
Регистрация: 09.02.2018
Сообщений: 27
|
|
В цикле for решил также присвоить каждому img в атрибут id номер текущей итерации i, а в обработчик события load добавил вывод this.id в alert. Интерпретатор сначала прошелся по циклу: создал и перезаписывал переменную img с обработчиками и атрибутом src. Затем, после окончания цикла, поочередно загрузились картинки и начали срабатывать обработчики события load (ну уже тут можно понять, что интерпретатор сохранил по img из каждой итерации как отдельные DOM объекты). Каждый из трех обработчиков в alert выводил разный id (0, 1, 2). То есть получается, в цикле for интерпретатор запоминал переменную img отдельно и сохранял все её данные в памяти, даже с перезаписью на новые данные. После окончания цикла for, но не выходя из основной функции, img в консоли выдал последний img с id = 2, ну а после выхода из основной функции img is not defined. Пока думаю, что из-за src интерпретатор, во время перезаписи переменной с незагруженным src, сохраняет в памяти этот DOM объект и ждет, когда в нем загрузиться src, а вследствие этого сработают обработчики события load и уже потом интерпретатор выкидывает этот DOM объект из памяти, т.к. функция, где создали данный DOM объект уже закончила свою работу. Причем забавно то, что когда я вышел из функции preloadImages, ну где создали переменную img, но перед загрузкой картинок и срабатыванием обработчиков события load, переменная img уже не была доступна. То есть мы не можем ссылаться хотя-бы на последний img из последней итерации for (ну тут еще понятно из-за чего, основная функция закончила работу и более не нужна --> все лок. переменные удалены из памяти), но все img сохранены в памяти, только теперь к ним нельзя обратиться из переменной.
Много букаф, но как мог описал ))
|
|
21.02.2018, 20:26
|
|
Профессор
|
|
Регистрация: 01.12.2016
Сообщений: 3,650
|
|
это то же самое что и
var a = 1;
var b = a;
a = undefined;
alert(b);
|
|
21.02.2018, 20:32
|
Интересующийся
|
|
Регистрация: 09.02.2018
Сообщений: 27
|
|
Ну тогда могу вопрос по другому задать) Почему DOM объекты img из трех итераций, после выхода из функции, которая их породила, еще остаются в памяти?
|
|
21.02.2018, 20:41
|
|
Профессор
|
|
Регистрация: 01.12.2016
Сообщений: 3,650
|
|
Потому что они нужны!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
for (var i = 0; i < 3; i++) {
var div = document.createElement('div');
div.textContent = i;
document.body.appendChild(div);
}
</script>
</body>
</html>
тут DOM элементы будут еще дольше сохраняться.
но перемеренная div тут не причем
|
|
21.02.2018, 20:52
|
Интересующийся
|
|
Регистрация: 09.02.2018
Сообщений: 27
|
|
Хм.. ну тут то понятно, что с document.body.appendChild(div) мы сохраняем этот элемент в DOM и можем в div что угодно теперь присваивать, все равно прошлый элемент будет храниться в памяти. Но у меня же DOM объект не добавляется в сам документ, он лишь создается, потом в него заносятся данные, но он нигде не используется и более никак недоступен, поэтому он вроде должен удаляться из памяти. Но сейчас уже начинаю вспоминать, что читал про то, что переменная в которую записан объект DOM, но который не добавляли на саму страницу все равно будет просто так храниться в памяти. То есть даже если эту переменную перезапишут, то старый DOM объект будет "летать в облаках". Это так?))) Просто у меня это не состыковывается с тем, что в JS, если на объект больше никто не ссылается, то он удаляется из памяти как мусор (даже если этот объект сам ссылается на кого-то). В моем случае, что удерживает эти img от удаления их сборщиком мусора?
|
|
22.02.2018, 12:56
|
|
Профессор
|
|
Регистрация: 07.03.2011
Сообщений: 1,138
|
|
Сообщение от BNB
|
Ну тогда могу вопрос по другому задать) Почему DOM объекты img из трех итераций, после выхода из функции, которая их породила, еще остаются в памяти?
|
Потому что у каждого из них есть событие onload. которое и держит ссылки на эти объекты и не дает сборщику мусора их убрать.
|
|
|
|