Τα κλεισίματα είναι ένα μοτίβο προγραμματισμού στη 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);
Ενώ μπορούμε να χρησιμοποιήσουμε άγκιστρα ({...}) αυθαίρετα για να δημιουργήσουμε μπλοκ, τα συναντάμε πιο συχνά γύρω από εντολές if, συναρτήσεις και κλάσεις.
const PI = 3.14;
// This function uses a closure for the value of PI (π)
function areaOfCircle(radius) {
return PI * radius * radius;
}