Приватные переменные с замыканиями
Скрывайте состояние внутри области видимости функции.
«Приватные переменные с замыканиями» — бесплатный урок JavaScript Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения JavaScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс JavaScript Academy содержит 4 уроков всего.
Приватность с помощью замыканий
В JavaScript долго не было встроенного способа сделать поля объекта приватными. Замыкания предоставляют такой способ: переменные внутри функции невидимы снаружи, но доступны функциям, определённым внутри неё.
function secretBox() {
let secret = "hidden";
return {
reveal: () => secret
};
}
const box = secretBox();
console.log(box.reveal()); // "hidden"
console.log(box.secret); // undefinedСчётчик с приватным состоянием
Классический пример: счётчик, значение которого нельзя напрямую изменить извне. Изменять его могут только возвращённые методы.
function makeCounter() {
let count = 0;
return {
increment: () => ++count,
value: () => count
};
}
const c = makeCounter();
c.increment();
c.increment();
console.log(c.value()); // 2Состояние недоступно для прямого изменения
Извне невозможно получить доступ к count. Попытки прочитать его возвращают undefined; необходимо использовать методы.
function makeCounter() {
let count = 0;
return { inc: () => ++count, get: () => count };
}
const c = makeCounter();
c.count = 100; // creates an unrelated property
console.log(c.get()); // 0 - real count untouchedОбеспечение правил
Поскольку доступ проходит через методы, вы можете обеспечивать инварианты, например не допускать отрицательного баланса.
function account(start) {
let balance = start;
return {
withdraw: (n) => {
if (n > balance) return "insufficient";
balance -= n;
return balance;
},
balance: () => balance
};
}
const a = account(100);
console.log(a.withdraw(150)); // "insufficient"
console.log(a.withdraw(40)); // 60Несколько приватных полей
Одно замыкание может одновременно защищать несколько переменных. Все они скрыты и доступны только возвращённым методам.
function user(name) {
let logins = 0;
let lastSeen = null;
return {
login: () => { logins++; lastSeen = "now"; },
stats: () => ({ name, logins, lastSeen })
};
}
const u = user("Ada");
u.login();
console.log(u.stats()); // { name: "Ada", logins: 1, lastSeen: "now" }Приватные вспомогательные функции
Скрывать можно не только данные, но и внутренние функции. Публичными становятся только методы, которые вы предоставляете.
function temperature() {
let celsius = 0;
const toF = (c) => c * 9 / 5 + 32; // private
return {
set: (c) => { celsius = c; },
fahrenheit: () => toF(celsius)
};
}
const t = temperature();
t.set(100);
console.log(t.fahrenheit()); // 212Независимые экземпляры
Каждый вызов фабричной функции создаёт отдельное приватное состояние, поэтому экземпляры никогда не влияют друг на друга.
function makeCounter() {
let n = 0;
return { inc: () => ++n };
}
const a = makeCounter();
const b = makeCounter();
console.log(a.inc(), a.inc()); // 1 2
console.log(b.inc()); // 1Доступ только для чтения
Предоставьте геттер без сеттера, чтобы сделать значение доступным только для чтения снаружи, сохранив возможность изменять его внутри.
function timer() {
let ticks = 0;
setupInternally();
function setupInternally() { ticks = 3; }
return { ticks: () => ticks };
}
const t = timer();
console.log(t.ticks()); // 3 - no way to set it outsideСравнение: поля класса
Современный JavaScript также поддерживает приватные поля класса #private. Замыкания по-прежнему полезны для фабричных функций и случаев, когда нужна приватность без классов.
class Counter {
#count = 0;
inc() { return ++this.#count; }
}
const c = new Counter();
console.log(c.inc()); // 1Почему это работает
Возвращённые методы являются замыканиями над внешними переменными. Внешняя функция уже завершила работу, но её область видимости продолжает существовать, потому что на неё всё ещё ссылаются эти замыкания.
Кэш для мемоизации
Приватное состояние отлично подходит для кэшей. Объект кэша остаётся скрытым и сохраняется между вызовами.
function memoSquare() {
const cache = {};
return (n) => {
if (cache[n] === undefined) cache[n] = n * n;
return cache[n];
};
}
const sq = memoSquare();
console.log(sq(4)); // 16
console.log(sq(4)); // 16 (cached)Быстрая проверка
Приватные переменные с помощью замыканий.
Повторение
Замыкания обеспечивают приватность: переменные внутри фабричной функции недоступны снаружи, но доступны возвращённым методам. Это позволяет создавать защищённые от изменений счётчики, балансы с инвариантами, скрытые вспомогательные функции и кэши. Каждый вызов фабричной функции создаёт независимое состояние. Современные приватные поля класса #private являются альтернативой, но замыкания особенно удобны в коде с фабричными функциями.
Часто задаваемые вопросы
Урок «Приватные переменные с замыканиями» бесплатный?
Да — полный текст урока «Приватные переменные с замыканиями» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс JavaScript Academy, подпишись на CoddyKit PRO. Курс JavaScript Academy содержит 4 уроков всего.
Чему я научусь в уроке «Приватные переменные с замыканиями»?
Скрывайте состояние внутри области видимости функции. Ты практикуешь JavaScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать JavaScript Academy?
Предыдущий опыт не требуется. JavaScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «Приватные переменные с замыканиями»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке JavaScript Academy?
Да. Каждый урок JavaScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Как замыкания захватывают состояние
- Приватные переменные с замыканиями
- Модульный шаблон (IIFE)
- Функции-фабрики