الـ Closure في JavaScript
أولاً: إيه هو الـ Closure؟
الـ Closure هو لما function بتتذكر المتغيرات اللي كانت في نطاقها (scope) حتى بعد ما الـ function الأم خلصت تشتغل.
يعني ببساطة: function جوه function بتقدر توصل لمتغيرات الأم حتى بعد ما الأم انتهت.
ثانياً: مثال بسيط يوضح الفكرة
function makeGreeting(name) {
// المتغير ده موجود في scope الـ makeGreeting
let message = "أهلاً يا " + name;
// الـ inner function بتتذكر message حتى بعد ما makeGreeting خلصت
function greet() {
console.log(message);
}
return greet;
}
let sayHello = makeGreeting("ياسين");
sayHello(); // أهلاً يا ياسينإيه اللي حصل هنا؟
makeGreeting اتنادت وخلصت.
لكن sayHello لسه بتتذكر المتغير message اللي كان جواها.
ده هو الـ Closure — الـ greet function احتفظت بـ scope بتاعها.

ثالثاً: ليه الـ Closure مهم؟
1. إخفاء البيانات (Data Privacy)
الـ Closure بيخليك تعمل متغيرات "خاصة" مش أي حد يقدر يوصلها من بره.
function makeCounter() {
let count = 0; // المتغير ده مش متاح من بره خالص
return {
increment() {
count++;
console.log("العداد: " + count);
},
decrement() {
count--;
console.log("العداد: " + count);
},
getCount() {
return count;
}
};
}
let counter = makeCounter();
counter.increment(); // العداد: 1
counter.increment(); // العداد: 2
counter.decrement(); // العداد: 1
console.log(counter.count); // undefined — مش قادر يوصلها!
console.log(counter.getCount()); // 1 — بس عن طريق الـ methodشايف؟ المتغير count محمي تماماً من الخارج، بس الـ functions الجوانية بتوصله بسهوله
الـ Factory Functions
بدل ما تعمل class، تقدر تعمل function بتولّد objects بمتغيرات مختلفة.
function makeMultiplier(x) {
return function(y) {
return x * y;
};
}
let double = makeMultiplier(2);
let triple = makeMultiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
console.log(double(10)); // 20كل function اتعملت اتذكرت قيمة x الخاصة بيها. double دايماً بتتذكر إن x = 2 و triple بتتذكر إن x = 3.
الـ Partial Application
تقدر "تجهز" function بجزء من الـ arguments وتسيب الباقي لوقت لاحق.
function add(x) {
return function(y) {
return x + y;
};
}
let addTen = add(10);
console.log(addTen(5)); // 15
console.log(addTen(20)); // 30
console.log(addTen(1)); // 11عملنا addTen مرة واحدة، ودلوقتي نقدر نستخدمها مع أي رقم وهي دايماً بتضيف 10.
رابعاً: غلطة شهيرة مع الـ Closure في الـ Loop
ده مثال بيلخبط ناس كتير:
// ❌ الطريقة الغلط
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
// بيطبع: 3, 3, 3 — مش 0, 1, 2 !ليه بيطبع 3 مرات؟
لأن var مش بتعمل block scope، فكل الـ functions بتشترك في نفس المتغير i، ولما الـ setTimeout ينفذ يكون i وصل لـ 3.
// ✅ الحل باستخدام let
for (let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
// بيطبع: 0, 1, 2 ✓let بتعمل نسخة جديدة من i لكل iteration، فكل closure بتتذكر قيمتها الخاصة
خامساً: Closure مع IIFE
الـ IIFE (Immediately Invoked Function Expression) هي function بتتنفذ على طول، وكمان بتعمل Closure.
let score = (function() {
let points = 0;
return {
add(n) { points += n; },
remove(n) { points -= n; },
show() { console.log("النتيجة: " + points); }
};
})();
score.add(10);
score.add(5);
score.remove(3);
score.show(); // النتيجة: 12الـ IIFE اتنفذت على طول وخلّت لنا object بـ methods بتوصل لـ points بشكل خاص.
سادساً: Closure في الحياة الواقعية (Real World)
مثال: زرار بيحسب كل ما اتضغط عليه
function makeButtonCounter(buttonName) {
let clicks = 0;
return function() {
clicks++;
console.log(`زرار "${buttonName}" اتضغط ${clicks} مرات`);
};
}
let likeBtn = makeButtonCounter("اعجبني");
let shareBtn = makeButtonCounter("شاركه");
likeBtn(); // زرار "اعجبني" اتضغط 1 مرات
likeBtn(); // زرار "اعجبني" اتضغط 2 مرات
shareBtn(); // زرار "شاركه" اتضغط 1 مرات
likeBtn(); // زرار "اعجبني" اتضغط 3 مراتكل زرار عنده عداده الخاص، محدش بيأثر على التاني
خاتمه
الـ Closure مش حاجة صعبة أو مرعبة — هي مجرد إن الـ function بتتذكر المكان اللي اتولدت فيه. لما تستوعب الفكرة دي هتلاقيها في كل حتة: في الـ React hooks، في الـ callbacks، في الـ modules، وفي كتير من الـ patterns المشهورة.