Замикання - це програмний прийом у JavaScript, який дозволяє використовувати змінні із зовнішньої лексичної області видимості всередині вкладеного блоку коду. JavaScript підтримує замикання прозоро, і їх часто використовують, навіть не знаючи, що це таке.
// Top-level declarations are global-scope
const dozen = 12;
// Functions create a new function-scope and block-scope.
// Referencing the outer variable here is a closure.
function nDozen(n) {
return dozen * n;
}
Назва замикання історично походить від λ-числення і була популяризована мовою Scheme (джерело) на позначення відкритих і закритих звʼязувань змінних функції.
Приватність даних / Інкапсуляція даних
// Consider this function:
const saveNumber = (number) => {
// The saved value is unaccessible by the outer lexical scope.
const value = number;
// We can provide access to the primitive value with a function, but the original will never change
return () => value;
};
// Attempting to set the variable outside of its lexical scope results in an error
value = 42;
Часткове застосування
// The arguments are applied one-by-one, using closures to arrive at the final result
function partialBuildUri(scheme) {
return function (domain) {
return function (path) {
return `${scheme}://${domain}/${path}`;
};
};
}
// A function could apply them all at once.
function buildUri(scheme, domain, path) {
return partialBuildUri(scheme)(domain)(path);
}
// Or apply a few to create a flexible system of functions for reuse.
function buildHttpsExercismUri(path) {
return partialBuildUri('https')('exercism.org');
}
У будь-якій мові програмування замикання тісно повʼязані з областю видимості змінних. У JavaScript є 3 типи лексичної області видимості для змінних:
var.{...}) за допомогою ключових слів let і const.На практиці замикання часто виникає тоді, коли функція (або блок) використовує змінну із зовнішньої області видимості. У JavaScript це підтримується прозоро, тож замикання часто використовують, навіть не згадуючи про них.
Ключове слово var визначає змінну з областю видимості функції. Це означає, що змінні, визначені через var, доступні будь-де у функції, де їх визначено, і в будь-якій вкладеній лексичній області видимості (чи то функції, чи то блоку).
{
var five = 5;
}
// This will succeed because 'five' exists in the same scope
var tenTimes = five * 10;
Ключові слова let і const визначають змінні з областю видимості блоку. let визначає змінну, яку можна змінювати: їй можна присвоювати значення багато разів, і її можна визначити, але не ініціалізувати. const визначає змінну, яку потрібно ініціалізувати під час визначення, і після цього її значення не може змінитися. Якщо змінній const присвоєно примітивне значення, його не можна змінити. Якщо змінній const присвоєно посилальне значення, як-от масив чи обʼєкт, саме посилання змінити не можна, але вміст масиву можна змінювати.
Розгляньмо цей блок:
// 'two' is defined at the top-level, therefore available to the global-scope
const two = 2;
{
// This succeeds, as 'two' is available from the outer lexical scope
const oneLess = two - 1;
}
// This throws an error because oneLess is not defined outside of the previous inner lexical scope
console.log(oneLess);
Хоча фігурні дужки ({...}) можна використовувати довільно, щоб створювати блоки, найчастіше вони трапляються навколо умовних конструкцій, функцій і класів.
const PI = 3.14;
// This function uses a closure for the value of PI (π)
function areaOfCircle(radius) {
return PI * radius * radius;
}