اذهب إلى المحتوى

السؤال

Recommended Posts

  • 0
نشر

في تطوير البرمجيات، يُشير مصطلح "الإغلاق" (Closure) إلى مفهوم يسمح للدالة بالوصول إلى المتغيرات  اللى محيطة بها حتى بعد الانتهاء من تنفيذها، يعتبر هذا مهمًا في اللغات التي تدعم التعريفات المتداخلة للدوال (nested functions)، حيث يمكن للدالة الداخلية (المحتواة داخل دالة أخرى) أن تستخدم المتغيرات المحيطة بها حتى بعد ما تخلص تنفيذ الدالة الخارجية.

الإغلاق يحدث عندما تُنشئ دالة داخلية في نطاق (scope) دالة أخرى وتستخدم متغيرات من نطاق الدالة الخارجية. عندما يتم تنفيذ الدالة الداخلية، فإنها تحتفظ بإمكانية الوصول إلى المتغيرات التي كانت متاحة في النطاق الخارجي في وقت تعريفها.

الإغلاق يمكن أن يكون ذا قيمة خاصة عند التعامل مع التعامل مع المعالجات الحدثية (Event Handling) أو عند استخدام دوال رد الاتصال (Callback Functions) حيث يمكن للإغلاق أن يحمل متغيرات معينة في الوقت الذي يتم استدعاء فيه.

وهذا مثال للتوضيح JavaScript:

function outerFunction() {
  let outerVariable = 'I am outer!';
  
  function innerFunction() {
    console.log(outerVariable); // يمكن للدالة الداخلية استخدام outerVariable
  }
  
  return innerFunction;
}

let closureExample = outerFunction();
closureExample(); // الإغلاق يسمح للدالة الداخلية بالوصول إلى outerVariable حتى بعد انتهاء تنفيذ outerFunction.

هذا المثال يظهر كيف يمكن للدالة الداخلية (innerFunction) في الداله الخارجية outerFunction أن تتمكن من الوصول إلى المتغير outerVariable حتى بعد انتهاء تنفيذ outerFunction.

  • 0
نشر (معدل)

ال closure ببساطة بيتيح للدوال الداخلية انها تستخدم المتغيرات الموجودة في الدوال التي تحتويها 
الق نظرة على هذا المثال وتابع الشرح 
 

function outer() {
  let x = "انا متغير في الدالة الخارجية";

  function inner() {
    console.log(x);
  }

  return inner;
}

const closureExample = outer();
closureExample(); // سيطبع " انا متغير في الدالة الخارجية" 

نلاحظ هنا ان الدالة inner هي دالة داخل الدالة outer وتقوم الدالة outer بإرجاعها كقيمة، بينما الدالة inner تستخدم المتغير  x في دالة الطباعة console.log ، وهذا ما يتيحه ال closure باختصار، يتيح سماحية استخدام المتغيرات المعرفة في نطاق الدالة التي تحمل في طيها دالة أخرى(حتى بعد انتهاء تنفيذ الدالة outer ) ، والمعروف أيضاً بال scope، وهي المنطقة او الحيز الذي تم تعريف الدوال والمتغيرات فيه. 
فهمك لل closure يساعدك في بناء كود مرن وفعال، جرب ان تبني دوال بداخل دوال واضافة متغيرات في كل scope لتجربة وفهم ال closure جيداً.

تم التعديل في بواسطة Hossam Mohamed15
  • 0
نشر

يمكن تحديد امكانية الوصول الي التغيرات بأحدي الطريقتين 

local : ونستطيع خلالها الوصول للمتغير بداخل اقواس التعريف التي تحتويه ولا يمكننا الوصول اليه خارجها 

global : وخلالها نستطيع الوصول الي المتغير في أي مكان بداخل البرنامج 

، Closure هو ببساطة دالة (function) تحتفظ بالحالة (state) المحيطة بها والتي تسمى (lexical environement). هذه الحالة تعبر عن المتغيرات الموجودة ضمن نطاق (scope) الدالة الخارجية (outer function) التي تحتوي هذه الدالة الداخلية (inner function).

في الصورة التالية 

 أولاً الدالة الخارجية تعرف متغيراً يسمى a وتسند له قيمة 5.
- الدالة الخارجية لديها دالة داخلية معرفة بداخلها.

- الدالة الداخلية تعرف متغيراً اسمه b وتسند له قيمة 10.

لا شيء جديد حتى الآن.

 الآن الدالة الداخلية تحاول طباعة المتغيرين a و b عن طريق العبارة console.log.

السؤال يأتي الآن، كيف للدالة الداخلية أن تعرف عن المتغير a الذي لم تقم بتعريفه بنفسها؟ هذا هو بالضبط ما يسمى Closure.

إذاً، مرة أخرى. Closure هو دالة تحتفظ بالحالة المحيطة بها (متغيرات) والتي تكون موجودة ضمن نطاق الدالة الخارجية.

1636792614_88310.thumb.png.3624ea624d72af13c8c21d604cbfd1d5.png

Global Variables

يمكن للدالة الوصول الي المتغيرات المنشئه بداخلها 

1. يمكن استخدام المتغيرات العالمية في أي مكان في برنامجنا . 

2. يمكن استخدام هذا المتغير العالمي في مختلف ملفات header المستخدم . ويمكن أيضا تغيير المتغيرات العالمية برمجيا.

3. عمر أو نطاق المتغير المحلي هو فقط ضمن إجراء أو كتلة في حين أن نطاق المتغير العالمي هو طوال البرنامج.

4. في حين يمكن إجراء تعديلات في متغير عالمي من أي مكان، فإنه لا يمكن القيام به مع المتغيرات المحلية.

5. ميزة إضافية من المتغير المحلي هو أنه يجعل من الأسهل لتصحيح وصيانة التطبيقات. ولكن في حالة المتغيرات العالمية، لا يمكن للمرء أن يكون متأكدا في أي وظيفة سيتم تعديلها أو عندما سيتم تعديل القيم المتغيرة. من ناحية أخرى، في متغير محلي، لا يوجد شيء لتتبع.
 

function myFunction() {  let a = 4;  return a * a;}

ويمكنها ايضا الوصول المتغيرات التي تم انشائها خارجها وفي هذه الحالة يكون المتغير من النوع global
 

<script>let a = 4;myFunction();function myFunction() {  document.getElementById("demo").innerHTML = a * a;}
function myFunction() {  a = 4;}

في صفحات الويب تنتمي المتغيرات التي من النوع global الي window object 

Global variables : يمكننا الوصول اليها واستخدامها او تغيير قيمتها من اي مكان بداخل الكود

local variables : لا يمكننا الوصول اليها من اي مكان خارج الدالة التي تم انشائه خلالها

اي متغير نقوم بأنشائه باستخدام الانواع التالية (var او let او const ) يكون بشكل تلقائي من النوع global واي نوع اخر من البيانات يكون من النوع local 


JavaScript Closures

 يتم ارجاع قيمة الدالة ( )add في حالة الاستدعاء الذاتي 

دالة الاستدعاء الذاتي بتم تنفيذها مره واحده فقط وتقوم خلالها بأعادة تعيين قيمة المتغير الي صفر 

يمكننا الوصول الي المتغير بداخل الدالة الفرعية الموجودة بداخل دالة ( )add علي الرغم من انشائه خارجها 
 

const add = (function () {  let counter = 0;  return function () {counter += 1; return counter}})();add();add();add();/* the counter is now 3 */

ال closure هو عبارة عن دالة لها حق الوصول الي النطاق الأصلي حتي بعد اغلاق الدالة الرئيسية 

  • 0
نشر

ال closure (الإغلاق) : يشير هذا المصطلح الى أنه يمكن للدوال الداخلية الوصول إلى المتغيرات بداخل نطاق الدوال الخارجية حتى بعد الانتهاء من تنفيذ الدالة الخارجية.
ده مثال بسيط

function outer() {
    const b = 50;
    function inner() {
        const a = 100;
        console.log(`a is ${a} and b is ${b}, the sum is ${a + b}`);
    }
    return inner;
}
const fnFirst = outer(); 
// هنا تم تنفيذ الدالة الخارجية وانتهت وكل متغير داخلها أصبح غير موجود ونتيجتهاارجاع الدالة الداخلية بالطبع أخذت حق الوصول إلى القيمة b
 fnFirst()
//هنا تم تنفيذ ما بداخل الدالة الداخلية بالرغم من أن المتغير لم يعد موجود
//بعدالاستدعاء سيتم طباعة
a is 100 and b is 50, the sum is 150

ولكن فيما يفيدنا في الحقيقة ويتم توفيره لنا مثال مفيد أكثر يوضح لما نستخدم الclosure
في هذا المثال هنا استدعينا الدالة في كل مرة اريد تنفيذ الدالة بنفس المعاملات في أى مكان ارسل لها المعاملات

function greeting(firstName, lastName) {
  var message = "Hello " + firstName + " " + lastName + "!";
  console.log(message);
}
greeting("Billy", "Bob"); //Hello Billy Bob!
greeting("Billy", "Bob"); //Hello Billy Bob!
greeting("Billy", "Bob"); //Hello Billy Bob!
greeting("Luke", "Schlangen");//Hello Luke Schlangen!
greeting("Luke", "Schlangen");//Hello Luke Schlangen!
greeting("Luke", "Schlangen");//Hello Luke Schlangen!

ولكن مع الclosure يوفر لنا اننا ننفذ الدالة الخارجية ونرسل لها المعاملات ويتم الوصول له بالدالة الداخلية.

function greeting(firstName, lastName) {
  var message = "Hello " + firstName + " " + lastName + "!";

  return function() {
    console.log(message);
  }
}

var greetingBilly = greeting("Billy", "Bob");
var greetingLuke = greeting("Luke", "Schlangen");

greetingBilly();//Hello Billy Bob!
greetingBilly();//Hello Billy Bob!
greetingBilly();//Hello Billy Bob!
greetingLuke();Hello Luke Schlangen!
greetingLuke();Hello Luke Schlangen!
greetingLuke();Hello Luke Schlangen!

مثال أخر يبين أنه بعد تنفيذ الدالة الخارجية وانتهائها والوصول للمتغير b نستطيع أن نتحكم في b بالرغم من انتهاء الدالة الخارجية 

function outer() {
  const a = 10;
  let b = 100;

  function inner() {
    let c = 20;
    console.log(`a=${a}, b=${b}, c=${c}`);
    b++;
    c++;
  }

  return inner;
}

const fnFirst = outer();//تم استدعاء الدالة الخارجية ونتيجة تم تخزينها في fnFirst
const fnSecond = outer();// تم استدعاء الدالة الخارجية مرة أخري ونتيجة تم تخزينها في fnFirst

fnFirst(); // نتيجة الاستدعاء لأول مرة              a=10, b=100, c=20
fnFirst(); // نتيجة الاستدعاء لثانى مرة وزيادةb    a=10, b=101, c=20
fnFirst(); // نتيجة الاستدعاء لثانى مرة وزيادةb    a=10, b=102, c=20
fnSecond(); // نتيجة الاستدعاء لأول مرة             a=10, b=100, c=20

نلاحظ أن في كل مرة يتم استدعاء fnFirst بعد المرة الأولي يتم زيادة b ولكن لايتم زيادة c لأنه يعاد تعريفه مرة أخري
نلاحظ ايضا عند استدعاء fnSecond   لأول مرة يطبع b=100 لأنه أيضا أخذ حق الوصول لb من الدالة الخارجية
 

  • 0
نشر

ال Closure يعني القدرة على الوصول إلى المتغيرات من النطاق الخارجي داخل دالة محددة، حتى بعد انتهاء تنفيذ تلك الدالة.

لتفهم هذا بشكل أفضل، يجب تجربة بشكل عملي ساعطيك مثال يمكنك تجربته بنفسك عن طريق موقع debugg او اي محرر اكواد لديك
 

function init() {
  var name = "Mozilla"; // الاسم هو متغير محلي تم إنشاؤه بواسطة init
  function displayName() {
    // displayName() هي الوظيفة الداخلية التي تشكل closure
    console.log(name); // استخدام المتغير المعلن في الوظيفة الرئيسيه
  }
  displayName();
}
init();

عندما يتم استدعاء الدالة

 init()

، يتم إنشاء متغير محلي داخلها يسمى name وتعيينه لقيمة "Mozilla". ثم، يتم تعريف دالة داخلية جديدة تسمى

displayName()

.

داخل displayName، يتم استخدام المتغير name الذي تم إنشاؤه في الدالة الخارجية init، والذي يظل متاحاً بفضل الـ Closure.

أخيراً، يتم استدعاء الدالة displayName داخل الدالة init، وستطبع قيمة المتغير name التي تم تعيينها في الدالة الأم init، مما يظهر كيف يعمل الـ Closure في السماح للدوال الداخلية بالوصول إلى المتغيرات المحلية للدوال الخارجية حتى بعد انتهاء تنفيذها.

يمكنك تجربة الكود من هنا لفهم بتعمق 

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...