جلست ابحث لوقت شوي طويل عن فوائد استعمال closure لكن ما لقيت سبب مقنع كل الي فهمته ان الوصول يصير غير مباشر للدوال الداخلية فقط
ما فائدة استعمال closure في جافا سكريبت
في البداية دعني أوضح لك أمرًا ال closures في JavaScript يُطلق عليها أيضًا lexical scoping. أعتقد أن المصطلح الثاني سيجعل الأمور أبسط قليلًا في الفهم. فكلمة lexical تعني أين تمت كتابة متغير ما "موقع كتابة المتغير في الأكواد" و scoping تعني ما هي المتغيرات المتاح لنا الوصول إليها.
دعنا نأخذ المثال التالي. في هذا المثال لدينا دالة لها الاسم a في هذه الدالة قمنا بتعريف المتغر grandpa و هو يحمل السلسلة النصية 'grandpa' و هذه الدالة تقوم بإعادة return دالة أخرى تسمى b و في هذه الدالة قمنا بتعريف متغير يسمى father و له القيمة 'father' و الدالة b تقوم بإعادة دالة تسمى c و في هذه الدالة قمنا بتعريف متغير يسمى son و له القيمة 'son' هذه الدالة تقوم بإرجاع سلسلة نصية تحتوي القيم الخاصة بالثلاث متغيرات grandpa و father و son.
لاحظ النتيجة التي سنحصل عليها من تنفيذ هذا المثال، طبعًا إذا كنت قد عملت ب JS من قبل فبالطبع هذه النتيجة ستكون متوقعة بالنسبة لك. و لكن دعني أسأل سؤالًا، كيف تذكرت الدالة c قيمة المتغير grandpa ؟؟ فكما تعلم في JS عندما ينتهي تنفيذ دالة ما "a مثلًا" يتم حذف هذه الدالة من ال call stack و بالتالي قيمة المتغير الموجود داخلها تمحى من الذاكرة، إذًا كيف علمت الدالة c بقيم المتغيرات grandpa و father؟؟
هنا يأتي دور ال closure حيث أن ال engine الخاص ب JS يقوم بعمل مسح للأكواد قبل تنفيذها و في حال وجد أنه هناك دالة ما تشير إلى متغير موجود خارجها"في دالة سيتم تنفيذها أولًا مثلًا" سيقوم بالاحتفاظ بهذه المتغيرات في ال memory heap حتى تتمكن دالة ما من الوصول إلى المتغيرات الموجودة خارجها و لن يتم حذفها كالمعتاد.
حسنًا و لكن ما فوائد هذا الأمر "ال closure"؟؟ في الحقيقة ال closure له أهمية كبيرة و له العديد من الاستخدامات و لكن أهمها ما يلي:
• الفائدة الأولى لها هي أنها memory efficient لنأخذ المثال التالي:
لنفرض أنه لدينا دالة تسمى heavyTask في هذه الدالة نقوم بإنشاء مصفوفة مكونة من 7000 عنصر و نقوم بملئ هذه المصفوفة ب عناصر ما، و هذه الدالة تقوم بعمل return لأي عنصر من عناصر هذه الدالة حسب ال index الخاص بالعنصر. بالطريقة العادية في كل مرة سنقوم باستدعاء هذه الدالة للحصول على عنص ما سيتم إنشاء المصفوفة و إخراج العنصر ثم و حذفها و في المرة التالية سيتم إنشاء المصفوفة و إخراج العنصر ثم و حذفها و هكذا، أما في حالة استخدام ال closure فسيتم إنشاء المصفوفة مرة واحدة فقط و سيتم حفظها في الذاكرة حتى نتمكن من الحصول على البيانات منها في أي وقت دون الحاجة لإعادة انشائها.
• الفائدة الثانية هي Data Encapsulating ، و هي مشابهة تمامًا لل Immediately invoked function expresssions المعروفة حيث أن المتغيرات أو الدوال لا تكون جميعها معرضة للعامة
الـclosure ليست شيئاً تستعمله حين تريد استعماله بل حين تحتاج إليه، مثلاً ما فوائد استعمال المطرقة ؟ هذا سؤال غير منطقي وإنما السؤال المنطقي هو " متى نستعمل المطرقة" والجواب هو "حين نريد أن ندق مسماراً في الحائط مثلاً"
اﻵن لنسأل متى نستعمل closure ؟ ببساطة حين نمرر callback إلى تابع ويحتاج هذا الـcallback إلى متحول معرف خارجه، مثال:
var mainElement = document.getElementById("main")
setTimeout(() => {
mainElement.innerHTML="مرت ثلاث ثوان";
},3000)
يعتبر أهمية closure في
١. إخفاء تفاصيل التفيذ في لغة جافا سكريبت أو بمعني اصحي تعريف private ميثود او متغير داخل ميثود أخري . يمكن أن تجلبه فقط داخل مكان التعريف .
٢. تعريف ميثود داخل ميثود nested functions . مفيد في انك تسطيع استخدام متغيرات التي يتم تعريفها داخل مثيود اﻷخري .
يمكنك ملاحظة تم إنشاء ميثود داخل OuterFunction . فأن ميثود InnerFunction يمكنها استخدام متغير outerVariable .
يمكنك استخدام ميثود InnerFunction عن طريق استدعاء داخل OuterFunction .
سنقوم بشرح مثال للفهم أكثر ما يمكنك فعله مع closure .
التعليقات