المقدمة: لا تزال مقالة تمهيدية. هناك العديد من ميزات اللغة المهمة للغاية في JavaScript - الكائنات ، وميراث النموذج الأولي ، والإغلاق. من بينها ، الإغلاق هي ميزة لغة جديدة للمبرمجين الذين يستخدمون اللغة الثابتة التقليدية C/C ++. ستبدأ هذه المقالة بأمثلة لإدخال ميزات اللغة الخاصة بإغلاق JavaScript ، وتجمع بين بعض مواصفات لغة ECMASCRIPT لتمكين القراء من فهم الإغلاق بشكل أعمق.
ملاحظة: هذه المقالة مقالة تمهيدية ، ويتم تجميع المواد على الإنترنت. إذا كنت سيدًا ، فنحن نرحب بك لطرح الاقتراحات الفنية والآراء حول المقالة. تناقش هذه المقالة JavaScript ، ولا تريد مقارنة اللغات. إذا كنت غير مرتاح بشكل طبيعي مع JavaScript ، فيرجى أخذ التفاف.
ما هو الإغلاق
ما هو الإغلاق؟ الإغلاق هو الإغلاق ، وهي ميزة جديدة لا تملكها اللغات الثابتة. لكن الإغلاق ليس شيئًا معقدًا لدرجة أنها غير مفهومة. باختصار ، الإغلاق هي:
الإغلاق هي مجموعة من المتغيرات المحلية للوظيفة ، لكن هذه المتغيرات المحلية ستستمر في الوجود بعد عودة الوظيفة.
الإغلاق هي "كومة" الوظيفة ولا يتم إصدارها بعد إرجاع الوظيفة. يمكننا أيضًا أن نفهم أن مداخن الوظائف هذه لا يتم تخصيصها على المكدس ولكن يتم تخصيصها على الكومة.
عند تحديد وظيفة أخرى داخل وظيفة ، سيتم إنشاء إغلاق
التعريف الثاني أعلاه هو الوصف التكميلي الأول ، الذي يستخرج كائن موضوع الموضوع للتعريف الأول - الإغلاق هو مجموعة "متغير محلي" من الوظائف. إنه فقط يمكن الوصول إلى هذا المتغير المحلي بعد إرجاع الوظيفة. (هذا ليس تعريفًا رسميًا ، ولكن هذا التعريف يجب أن يكون أكثر مواتية لفهمك للإغلاق)
كمتغيرات محلية ، يمكن الوصول إليها بواسطة الكود في الوظيفة ، ولا يوجد فرق بين هذه اللغة الثابتة. الفرق بين عمليات الإغلاق هو أنه لا يزال من الممكن الوصول إلى المتغيرات المحلية بواسطة الكود خارج الوظيفة بعد تنفيذ الوظيفة. هذا يعني أن الوظيفة يجب أن تُرجع "مرجعًا" إلى الإغلاق ، أو تعيين هذا "المرجع" إلى متغير خارجي للتأكد من الوصول إلى المتغيرات المحلية في الإغلاق بواسطة الرمز الخارجي. بالطبع ، يجب أن يكون الكيان الذي يحتوي على هذا المرجع كائنًا ، لأنه في JavaScript ، كل الباقي باستثناء الأنواع الأساسية هي كائنات. لسوء الحظ ، لا يوفر ECMASCript الأعضاء والأساليب ذات الصلة للوصول إلى المتغيرات المحلية في الإغلاق. ومع ذلك ، في ECMASCRIPT ، فإن الوظيفة الداخلية المحددة في كائن الوظيفة هي متغير محلي يمكنه الوصول مباشرة إلى وظائف خارجية. من خلال هذه الآلية ، يمكننا إكمال الوصول إلى الإغلاق بالطريقة التالية.
نسخة الكود كما يلي:
وظيفة تحية (الاسم) {
var text = 'hello' + name ؛ // متغير محلي
// في كل مرة يتم إنشاء إغلاق ، ويتم إرجاع كائن الوظيفة الداخلية إلى المتصل
Return Function () {Alert (text) ؛ }
}
var sealhello = تحية ("الإغلاق") ؛
sealhello () // الوصول إلى النص المتغير المحلي من خلال الإغلاق
نتيجة التنفيذ للرمز أعلاه هي: Hello Closure ، لأنه بعد تنفيذ وظيفة التحية ، لا تزال وظيفة Sayhello () يمكنها الوصول إلى النص المتغير المحلي المحدد بداخله.
حسنًا ، هذا هو تأثير الإغلاق الأسطوري. تحتوي عمليات الإغلاق على العديد من سيناريوهات وأوضاع التطبيق في JavaScript ، مثل Singleton و Power Constructor وأنماط JavaScript الأخرى التي لا يمكن فصلها عن استخدام الإغلاق.
نموذج إغلاق ECMASCRIPT
كيف تنفذ ECMASCRIPT؟ إذا كنت ترغب في الحصول على فهم متعمق ، فيمكنك الحصول على مواصفات ECMAScript للبحث. سأقدم فقط تفسيرًا بسيطًا هنا ، ويأتي المحتوى أيضًا من الإنترنت.
عند تشغيل وظيفة البرنامج النصي ECMASCRIPT ، يكون لكل جمعية دالة سيناريو سياق التنفيذ (سياق التنفيذ) ، الذي يحتوي على ثلاثة أجزاء.
البيئة المعجمية
البيئة المتغيرة
هذا الارتباط
النقطة الثالثة لهذا الارتباط لا علاقة لها بالإغلاق ولا تتم مناقشتها في هذه المقالة. معرف متغير يستخدم في البيئة النحوية لتحليل عملية تنفيذ الوظائف. يمكننا أن نفكر في بيئة نحوية ككائن يحتوي على عنصرين مهمين ، وسجل البيئة (إعادة ترميز البيئة) ، ومرجع خارجي (مؤشر). يحتوي سجل البيئة على متغيرات محلية ومتغيرات المعلمات التي تم إعلانها داخليًا من خلال الوظيفة ، ويشير المرجع الخارجي إلى سيناريو تنفيذ السياق لكائن الوظيفة الخارجية. هذه القيمة المرجعية لاغية في سيناريو السياق العالمي. تشكل هيكل البيانات هذه قائمة مرتبطة في اتجاه واحد ، ويشير كل مرجع إلى سيناريو السياق الخارجي.
على سبيل المثال ، يجب أن يكون نموذج الإغلاق في مثالنا أعلاه مثل هذا. تكون وظيفة Sayhello في أدنى مستوى ، والمستوى العلوي هو تحية الوظيفة ، والمستوى الخارجي هو المشهد العالمي. كما هو موضح في الشكل أدناه: لذلك ، عندما يتم استدعاء Sealhello ، سيجد Sayhello قيمة النص المتغير المحلي من خلال مشهد السياق ، وبالتالي فإن البيئة المتغيرة "Hello Closure" (البيئة المتغيرة) وبيئة القواعد هي نفسها بشكل أساسي. للاختلافات المحددة ، يرجى الرجوع إلى وثيقة مواصفات ECMASCRIPT.
عينة عمود الإغلاق
في المقالة السابقة ، أفهم تقريبًا ماهية إغلاق JavaScript وكيف يتم تنفيذ عمليات الإغلاق في JavaScript. أدناه سوف نساعدك على فهم الإغلاق بشكل أعمق من خلال استهداف بعض الأمثلة. هناك 5 أمثلة أدناه ، والأمثلة هي من إغلاق JavaScript للدمى (المرآة). مثال 1: المتغيرات المحلية في عمليات الإغلاق هي مراجع بدلاً من نسخ
نسخة الكود كما يلي:
وظيفة seal667 () {
// المتغير المحلي الذي ينتهي داخل الإغلاق
var num = 666 ؛
var siberalert = function () {Alert (num) ؛ }
num ++ ؛
عودة يقول.
}
var saysalert = say667 () ؛
Sayalert ()
لذلك ، يجب أن تظهر نتيجة التنفيذ 667 بدلاً من 666.
مثال 2: تربط وظائف متعددة نفس الإغلاق لأنه يتم تعريفها ضمن نفس الوظيفة.
نسخة الكود كما يلي:
وظيفة setupSomeGlobals () {
// المتغير المحلي الذي ينتهي داخل الإغلاق
var num = 666 ؛
// تخزين بعض الإشارات إلى وظائف كمتغيرات عالمية
galertnumber = function () {Alert (num) ؛ }
gincreasenumber = function () {num ++ ؛ }
gsetNumber = function (x) {num = x ؛ }
}
SETUPSOMEGLOBALS () ؛ // تعيين القيم لثلاثة متغيرات عالمية
Galertnumber () ؛ // 666
gincreasenumber () ؛
Galertnumber () ؛ // 667
GsetNumber (12) ؛ //
Galertnumber () ؛ // 12
مثال 3: عند تعيين وظائف في حلقة ، ستربط هذه الوظائف نفس الإغلاق
نسخة الكود كما يلي:
قائمة بناء الوظائف (قائمة) {
var result = [] ؛
لـ (var i = 0 ؛ i <list.length ؛ i ++) {
var item = 'item' + list [i] ؛
result.push (function () {Alert (item + '' + list [i])}) ؛
}
نتيجة العودة
}
وظيفة testlist () {
var fnlist = buildlist ([1،2،3]) ؛
// باستخدام J فقط للمساعدة في منع الالتباس - يمكن استخدام i
لـ (var j = 0 ؛ j <fnlist.length ؛ j ++) {
fnlist [j] () ؛
}
}
تتمثل نتيجة التنفيذ في قائمة الاختبار في أن النافذة غير المحددة للبند 3 تنبثق ثلاث مرات ، لأن هذه الوظائف الثلاث تربط نفس الإغلاق ، وقيمة العنصر هي النتيجة المحسوبة الأخيرة ، لكن عندما تقفز من الحلقة ، تكون قيمة I 4 ، وبالتالي فإن نتيجة القائمة [4] غير محددة.
مثال 4: جميع المتغيرات المحلية للوظائف الخارجية موجودة في الإغلاق ، حتى لو تم الإعلان عن هذا المتغير بعد تعريف الوظيفة الداخلية.
نسخة الكود كما يلي:
الوظيفة sekeralice () {
var sizenalert = function () {Alert (alice) ؛ }
// المتغير المحلي الذي ينتهي داخل الإغلاق
var alice = 'hello alice' ؛
عودة يقول.
}
var helloalice = sayalice () ؛
helloalice () ؛
نتيجة التنفيذ هي نافذة مع "Hello Alice" المنبثقة. حتى إذا أعلن المتغير المحلي بعد أن يقول الوظيفة ، لا يزال من الممكن الوصول إلى المتغير المحلي.
مثال 5: قم بإنشاء إغلاق جديد في كل مرة تسمى الوظيفة
نسخة الكود كما يلي:
وظيفة newclosure (Somenum ، Someref) {
// المتغيرات المحلية التي ينتهي بها المطاف داخل الإغلاق
var num = somenum ؛
var anarray = [1،2،3] ؛
var ref = someref ؛
وظيفة الإرجاع (x) {
num += x ؛
Anarray.push (num) ؛
التنبيه ('num:' + num +
'/nanarray' + anarray.toString () +
'/nref.somevar' + Ref.somevar) ؛
}
}
closure1 = newClosure (40 ، {somevar: 'closure 1'}) ؛
closure2 = newClosure (1000 ، {somevar: 'closure 2'}) ؛
إغلاق 1 (5) ؛ // num: 45 anarray [1،2،3،45] المرجع: 'Somevar closure1'
Closure2 (-10) ؛ // num: 990 Anarray [1،2،3،990] المرجع: 'Somevar closure2'
تطبيق الإغلاق
قطعة مفردة سينجلتون:
نسخة الكود كما يلي:
var singleton = function () {
var privatevariable ؛
وظيفة privatefunction (x) {
... Privatevariable ...
}
يعود {
FirstMethod: Function (A ، B) {
... Privatevariable ...
} ،
SecondMethod: Function (C) {
... privatefunction () ...
}
} ؛
} () ؛
يتم تحقيق هذه القطعة الفردية من خلال الإغلاق. يتم الانتهاء من تغليف الأعضاء والأساليب الخاصة من خلال الإغلاق. الوظيفة الرئيسية المجهولة إرجاع كائن. يحتوي الكائن على طريقتين ، يمكن أن تستخدم الطريقة 1 متغيرات خاصة ، ويمكن للأسلوب 2 الوصول إلى وظائف خاصة داخلية. الشيء الذي يجب ملاحظته هو "()" حيث تنتهي الوظيفة الرئيسية المجهولة. بدون هذا "()" ، لا يمكن إنتاج قطعة واحدة. نظرًا لأن الوظائف المجهولة يمكنها إرجاع كائنات فريدة فقط ولا يمكن استدعاؤها في مكان آخر. هذه هي طريقة استخدام عمليات الإغلاق لإنشاء قطع واحدة.