الإغلاقات نمط برمجي في 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;
}