Кодовая база
1.28K subscribers
16 photos
1 video
32 links
База во фронтенд разработке.

Написать в личку: https://t.iss.one/devmargooo
Download Telegram
Лексическое окружение

Начну серию постов, связанную с замыканиями, утечками памяти через замыкания, stale state и stale props в React. В Javascript есть три основные концепции, связанные с замыканиями:

🔹 Lexical environment
🔹 Environment record
🔹 Execution context

Сегодня поговорим о первой из них, а именно - о лексическом окружении.

🔶 Лексическое окружение - это структура, которая определяет, какие идентификаторы (т.е. переменные) доступны в данном фрагменте кода. Создается в момент вызова. Фрагментами кода, которые создают новое лексическое окружение, являются:

🔹 Js файлы. Когда мы запускаем код из js файла, создается глобальное лексическое окружение, и переменные из него будут доступны в любом месте в этом файле
🔹Функции. Вызов функции создает новое лексическое окружение для нее, повторный вызов создаст новое лексическое окружение
🔹Блок кода (то, что внутри {}). Когда интерпретатор доходит до блока кода, он создает новое лексическое окружение, в котором могут находиться переменные, объявленные через let и const.

Каждое лексическое окружение имеет ссылку на внешнее лексическое окружение. Для глобального лексического окружения ссылка на внешнее будет равна null.

На картинке выше вы можете увидеть код и схематичное изображение его лексического окружения. Лексическое окружение foo содержит в себе идентификатор c и ссылку на внешнее лексическое окружение, которое является глобальным. Глобальное лексическое окружение содержит в себе два идентификатора, а его ссылка на внешнее лексическое окружение равна null.

#javascript #замыкание #lexical_environment
👍118
⚡️ Что такое замыкание и как оно приводит к утечкам памяти

В прошлый раз мы с вами говорили о лексическом окружении и причинах его создания, а сегодня поговорим о замыканиях. Термином “замыкание” в javascript обозначает функцию и ее лексическое окружение. Как вы помните, лексическое окружение в javascript содержит в себе ссылку на внешнее лексическое окружение - таким образом, все внешние лексические окружения для функции будут доступны ей через цепочку ссылок.

Что происходит с лексическим окружением функции после того, как она завершила свою работу? Довольно часто оно больше не нужно и уничтожается, однако бывает и иначе. Рассмотрим пример:

function makeCounter() {
let count = 0;
const increment = () => count++;
return increment;
}
let counter = makeCounter();
counter();
counter();


Функция makeCounter завершила свою работу, однако лексическое окружение, которое она создала - с идентификатором count в нем - осталось в памяти. Почему так? Потому что лексическое окружение функции makeCounter - внешнее для лексического окружения функции increment, которая в нем создается. Когда мы вернули из makeCounter функцию increment, прицепом к ней мы вернули все ее лексическое окружение. Поскольку на это лексическое окружение ссылается increment (ниже counter - это две переменных указывают на одну область памяти), то лексическое окружение вместе с переменной count надежно зависло в памяти до тех пор, пока counter остается ссылочно доступен.

В данном случае makeCounter у нас “зависло” совсем маленькое лексическое окружение с переменной count - однако бывают и гораздо более серьезные утечки памяти, связанные с замыканиями. Такая ситуация происходит, если “зависшее” лексическое окружение занимает много места в памяти и/или ссылается на другие “тяжелые” лексические окружения. Вот здесь я писала об одной из таких утечек в Promise.race, а в следующий раз поговорим с вами о том, как “зависшее” лексическое окружение приводит к ситуациям, которые мы называем stale props и stale state.

#замыкание #javascript
117👍3