Celem closures
jest po prostu zachowanie stanu; stąd nazwa closure
- zamyka się nad stanem. Dla ułatwienia dalszych wyjaśnień użyję Javascript.
Zazwyczaj masz funkcję
function sayHello(){
var txt="Hello";
return txt;
}
gdzie zakres zmiennych jest związany z tą funkcją. Po wykonaniu zmienna txt
wychodzi poza zakres. Po zakończeniu wykonywania funkcji nie ma możliwości uzyskania do niej dostępu ani korzystania z niej.
Zamknięcia są konstrukcjami językowymi, które pozwalają - jak powiedziano wcześniej - zachować stan zmiennych i tym samym przedłużyć zakres.
Może to być przydatne w różnych przypadkach. Jednym z przypadków użycia jest konstrukcja funkcji wyższego rzędu .
W matematyce i informatyce funkcja wyższego rzędu (także forma funkcjonalna, funkcjonalna lub funktor) to funkcja, która wykonuje co najmniej jedną z następujących czynności: 1
- przyjmuje jedną lub więcej funkcji jako dane wejściowe
- wyprowadza funkcję
Prostym, ale co prawda niezbyt przydatnym przykładem jest:
makeadder=function(a){
return function(b){
return a+b;
}
}
add5=makeadder(5);
console.log(add5(10));
Definiujesz funkcję makedadder
, która przyjmuje jeden parametr jako dane wejściowe i zwraca funkcję . Istnieje funkcja zewnętrznafunction(a){}
i wewnętrzna. function(b){}{}
Następnie definiujesz (domyślnie) inną funkcję add5
w wyniku wywołania funkcji wyższego rzędu makeadder
. makeadder(5)
zwraca anonimową ( wewnętrzną ) funkcję, która z kolei przyjmuje 1 parametr i zwraca sumę parametru funkcji zewnętrznej i parametru funkcji wewnętrznej .
Trik jest to, że podczas zawracania wewnętrzną funkcję, która nie rzeczywiste dodanie zakres parametru funkcji zewnętrznej ( a
) jest zachowana. add5
pamięta , że parametr a
był 5
.
Lub pokazać przynajmniej jeden przydatny przykład:
makeTag=function(openTag, closeTag){
return function(content){
return openTag +content +closeTag;
}
}
table=makeTag("<table>","</table>")
tr=makeTag("<tr>", "</tr>");
td=makeTag("<td>","</td>");
console.log(table(tr(td("I am a Row"))));
Innym powszechnym przypadkiem użycia jest tak zwane wyrażenie funkcji IIFE = natychmiast wywołane. W javascript bardzo często fałszowane są prywatne zmienne członkowskie. Odbywa się to za pomocą funkcji, która tworzy prywatny zasięg = closure
, ponieważ jest on wywoływany natychmiast po wywołaniu definicji. Struktura jest function(){}()
. Zwróć uwagę na nawiasy ()
po definicji. Dzięki temu można go używać do tworzenia obiektów z odkrywającym wzorem modułu . Sztuką jest utworzenie zakresu i zwrócenie obiektu, który ma dostęp do tego zakresu po wykonaniu IIFE.
Przykład Addiego wygląda następująco:
var myRevealingModule = (function () {
var privateVar = "Ben Cherry",
publicVar = "Hey there!";
function privateFunction() {
console.log( "Name:" + privateVar );
}
function publicSetName( strName ) {
privateVar = strName;
}
function publicGetName() {
privateFunction();
}
// Reveal public pointers to
// private functions and properties
return {
setName: publicSetName,
greeting: publicVar,
getName: publicGetName
};
})();
myRevealingModule.setName( "Paul Kinlan" );
Zwrócony obiekt ma odwołania do funkcji (np. publicSetName
), Które z kolei mają dostęp do zmiennych „prywatnych” privateVar
.
Ale są to bardziej szczególne przypadki użycia dla Javascript.
Jakie konkretne zadanie wykonałby programista, któremu najlepiej byłoby zamknąć?
Jest tego kilka przyczyn. Być może jest to dla niego naturalne, ponieważ postępuje według funkcjonalnego paradygmatu . Lub w Javascript: po prostu trzeba polegać na zamknięciach, aby ominąć niektóre dziwactwa języka.