A closure-ök egy programozási minta a JavaScriptben, amely lehetővé teszi, hogy egy külső lexikai scope változóit egy egymásba ágyazott kódblokkon belül használjuk. A JavaScript átláthatóan támogatja a closure-öket, és gyakran anélkül használjuk őket, hogy tudnánk, mi is az.
// 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;
}
A closure név történetileg a λ-kalkuluszból származik, és a scheme tette népszerűvé (forrás), hogy egy függvény nyitott és zárt változókötéseire utaljon.
Adatvédelem / adatelkapszulázás
// 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;
Részleges alkalmazás
// 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');
}
Bármely programozási nyelvben a closure-ök szorosan összefüggenek a változók scope-jával. A JavaScriptben háromféle lexikai scope létezik a változók számára:
var kulcsszóval deklarálunk.{...}) belül a let és a const kulcsszóval deklarálunk.A gyakorlatban closure gyakran akkor jön létre, amikor egy függvény (vagy blokk) egy külső scope változóját használja. A JavaScriptben ez átláthatóan támogatott, ezért a closure-öket gyakran anélkül használjuk, hogy külön hivatkoznánk rájuk.
A var kulcsszó a függvény-scope-hoz kötött változókat definiálja. Ez azt jelenti, hogy a var-ral definiált változók mindenhol elérhetők abban a függvényben, ahol definiáltuk őket, valamint minden egymásba ágyazott lexikai scope-ban (legyen az függvény vagy blokk).
{
var five = 5;
}
// This will succeed because 'five' exists in the same scope
var tenTimes = five * 10;
A let és a const kulcsszó a blokk-scope-hoz kötött változókat definiálja. A let egy módosítható változót definiál, amelynek az értéke többször is beállítható, és lehet definiálva inicializálás nélkül. A const olyan változót definiál, amelyet a definiálásakor inicializálni kell, és az értéke utána nem változhat. Ha a const változó értéke primitív, akkor az nem módosítható. Ha a const változó értéke referenciatípus, például egy tömb vagy objektum, akkor maga a referencia nem változhat, de a tömb tartalma módosítható.
Nézzük ezt a blokkot:
// '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);
Bár a kapcsos zárójeleket ({...}) tetszőlegesen használhatjuk blokkok létrehozására, leggyakrabban elágazások, függvények és osztályok körül találkozunk velük.
const PI = 3.14;
// This function uses a closure for the value of PI (π)
function areaOfCircle(radius) {
return PI * radius * radius;
}