На этой неделе Шо и я провели презентацию концепции замыкания в JavaScript на Flatiron School Presents. Проводя исследование, мы столкнулись с одним недостатком использования замыканий: утечками памяти.
Утечка памяти происходит, когда программа запрашивает и занимает память, но фактически не использует ее. Компьютерная память хранится и извлекается из оперативной памяти (ОЗУ) точно так же, как краткосрочная память человека хранится в гиппокампе, очень специфической области нашего мозга. Память, которую временно хранит оперативная память, — это данные запущенных приложений.
К счастью, JavaScript — это язык «сборки мусора», который автоматически освобождает объекты и строки, которые больше не используются. Поэтому локальные переменные в функции освобождаются, когда функция их возвращает, и освобождает место для выделения другой памяти.
Но что, если функция является замыканием?
Чтобы дать понимание утечек памяти в JavaScript, я хотел бы указать на наиболее заметный атрибут замыкания. Тем не менее, я не буду вдаваться в концепцию закрытия в этом посте, так как само закрытие является огромной темой для обсуждения.
Замыкание — это дочерняя (внутренняя) функция, которая имеет доступ к области видимости своих родительских (внешних) функций. Чтобы быть более ясным, замыкания в JavaScript могут получить доступ к информации во внешних функциях, потому что они несут ссылки на переменные внешних функций, а не на фактическое значение. Например, если значение переменной y изменится с 15 на 5, функция g() сохранит обновленное значение 5.
Поскольку задача замыкания состоит в том, чтобы удерживать ссылку на область действия внешней функции, а не освобождаться, она занимает дополнительное место в оперативной памяти в вашей системе. Это явление очень похоже на определение утечек памяти, не так ли?
Это всего лишь один пример различных потенциальных причин утечек памяти в вашей системе. Другие причины, связанные с JavaScript, могут включать следующее:
- Использование таймеров или обратных вызовов, которые ссылаются на данные, которые больше не требуются
- Не удалять явно EventListeners, когда они не нужны за пределами локальной области
Чтобы проверить, сколько места в памяти занимают запущенные в данный момент приложения, вы можете найти Spotlight Search «Мониторинг активности» и щелкнуть вкладку «Память».
В этом конкретном примере у меня было открыто около 29 вкладок в Chrome с некоторыми другими приложениями. Монитор активности показывает, что все, что я делаю на своем компьютере в данный момент, занимает 7,01 ГБ / 8,00 ГБ ОЗУ.
Когда ОЗУ заполнено, содержимое сохраняется на жесткий диск, чтобы освободить место в ОЗУ. Этот процесс называется «обмен». В приведенном выше примере 227 МБ моего ОЗУ были заменены таким же объемом на моем жестком диске. Хотя доступ к данным, хранящимся в оперативной памяти, может быть мгновенным, для извлечения данных с жесткого диска требуется больше времени. В отличие от оперативной памяти, которая временно хранит данные, данные на диске сначала необходимо найти, прочитать и отправить в оперативную память, прежде чем они будут обработаны.
Итак, как узнать, есть ли утечка памяти? Утечки памяти не приводят к физическому или необратимому повреждению. Поскольку это проблема программного обеспечения, это замедлит работу приложений или даже всей вашей системы. Однако программа, занимающая много места в оперативной памяти, не всегда означает, что ее память куда-то утекает. Программе, которую вы используете, может действительно понадобиться столько места.
Ранее в посте я упомянул, что JavaScript — это язык сборки мусора. Сборка мусора запускается, когда память выделяется и теряется. Он ищет память, которая не используется, и возвращает ее системе, уменьшая вероятность утечек памяти (которые не вызваны замыканиями!)
Узнайте больше об использовании инструментов разработчика для обнаружения утечек памяти: