6.1 Поняття замикань
Замикання є однією з найбільш потужних і важливих концепцій у JavaScript. Вони дозволяють функціям запам'ятовувати своє лексичне оточення навіть після того, як вони були виконані. У цій лекції ми розглянемо поняття замикань, їх особливості та наведемо різні приклади їх використання.
Замикання (closure) у JavaScript — це комбінація функції та лексичного оточення, у якому ця функція була оголошена. Замикання дозволяє функції "запам'ятовувати" і отримувати доступ до змінних та інших функцій зі своєї зовнішньої області видимості навіть після того, як зовнішня функція була виконана.
Основні властивості замикань:
- Лексичне оточення: контекст, у якому була оголошена функція, включаючи всі змінні, доступні на момент оголошення.
- Збереження контексту: функція із замиканням може зберегти доступ до змінних із зовнішньої області видимості навіть після завершення виконання цієї зовнішньої функції.
6.2 Приклади роботи замикань
Приклад 1: Просте замикання
У цьому прикладі innerFunction() має доступ до змінної outerVariable зі своєї зовнішньої області видимості навіть після завершення виконання outerFunction().
function outerFunction() {
let outerVariable = 'Я з зовнішньої функції';
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
const closure = outerFunction();
closure(); // Виведе: Я з зовнішньої функції
Приклад 2: Лічильник з використанням замикання
У цьому прикладі функція-лічильник зберігає значення змінної count і збільшує його при кожному виклику.
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // Виведе: 1
console.log(counter()); // Виведе: 2
console.log(counter()); // Виведе: 3
Приклад 3: Замикання в циклі
Замикання часто використовуються для збереження значень змінних у циклах.
У цьому прикладі кожна функція всередині масиву arr "запам'ятовує" значення змінної i у момент свого створення завдяки блочній області видимості let:
function createArrayWithClosures() {
let arr = [];
for (let i = 0; i < 3; i++) {
arr[i] = function() {
console.log(i);
};
}
return arr;
}
const closures = createArrayWithClosures();
closures[0](); // Виведе: 0
closures[1](); // Виведе: 1
closures[2](); // Виведе: 2
6.3 Складні сценарії використання замикань
Приклад 1: Часткове застосування функції (partial application)
Замикання дозволяють створювати частково застосовані функції, зберігаючи деякі аргументи фіксованими.
У цьому прикладі функція multiply() повертає функцію, яка множить переданий їй аргумент b на зафіксований аргумент a.
function multiply(a) {
return function(b) {
return a * b;
};
}
const double = multiply(2);
console.log(double(5)); // Виведе: 10
console.log(double(10)); // Виведе: 20
Приклад 2: Приховування даних (data hiding)
Замикання можуть використовуватися для створення приватних змінних та методів.
У цьому прикладі змінні _name і _age є приватними та доступні лише через методи об'єкта:
function createPerson(name, age) {
let _name = name;
let _age = age;
return {
getName: function() {
return _name;
},
getAge: function() {
return _age;
},
setName: function(newName) {
_name = newName;
},
setAge: function(newAge) {
_age = newAge;
}
};
}
const person = createPerson('Джон', 30);
console.log(person.getName()); // Виведе: Джон
person.setName('Джейн');
console.log(person.getName()); // Виведе: Джейн
console.log(person.getAge()); // Виведе: 30
Приклад 3: Мемоізація
Мемоізація — це техніка оптимізації, при якій результати функції зберігаються, щоб уникнути повторних обчислень для однакових вхідних даних.
У цьому прикладі функція memoize() використовує замикання для збереження кешу обчислених результатів функції fn():
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key]) {
return cache[key];
}
const result = fn(...args);
cache[key] = result;
return result;
};
}
function slowFunction(num) {
console.log('Обчислення...');
return num * 2;
}
const memoizedFunction = memoize(slowFunction);
console.log(memoizedFunction(5)); // Виведе: Обчислення... 10
console.log(memoizedFunction(5)); // Виведе: 10 (результат взято з кешу)
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ