1. تعريف وظيفة رد الاتصال
وظيفة رد الاتصال هي وظيفة تسمى من خلال مؤشر الوظيفة. إذا قمت بتمرير المؤشر (العنوان) للوظيفة كوسيطة لوظيفة أخرى ، عند استخدام هذا المؤشر لاستدعاء الوظيفة التي يشير إليها ، نقول إن هذه وظيفة رد اتصال. لا يتم استدعاء وظيفة رد الاتصال مباشرة من قبل تطبيق الوظيفة ، ولكن يطلق عليها طرف آخر عند حدوث حدث أو شرط معين ، ويستخدم للرد على الحدث أو الحالة.
في JavaScript ، يتم تمرير التعريف المحدد لوظيفة رد الاتصال: الوظيفة A تم تمريرها كمعلمة (مرجع الوظيفة) في وظيفة أخرى B ، وتنفيذ هذه الوظيفة B الوظيفة A. دعنا نقول أن الوظيفة A تسمى وظيفة رد الاتصال. إذا لم يكن هناك اسم (تعبير وظيفة) ، يطلق عليه وظيفة رد الاتصال المجهول. لذلك ، لا يتم استخدام رد الاتصال بالضرورة للتزامن. غالبًا ما يتم استخدام عمليات الاسترجاعات في سيناريوهات متزامنة عامة (حظر) ، مثل طلب تنفيذ بعض العمليات وتنفيذ وظيفة رد الاتصال.
مثال
مثال على استخدام عمليات الاسترجاعات في المزامنة (الحظر) هو تنفيذ FUNC2 بعد تنفيذ رمز FUNC1.
var func1 = function (callback) {// افعل شيئًا. (callback && typeof (callback) === "function") && callback () ؛} func1 (func2) ؛ var func2 = function () {}2. استخدم مناسبات وظيفة رد الاتصال
تحميل الموارد: قم بتنفيذ رد الاتصال بعد التحميل الديناميكي لملفات JS ، وقم بتنفيذ رد الاتصال بعد تحميل iframe ، وتنفيذ رد الاتصال بعد تحميل رد الاتصال Ajax ، وتنفيذ رد الاتصال بعد تحميل الصورة ، Ajax ، إلخ.
تعتمد أحداث DOM وأحداث Node.js على آلية رد الاتصال (قد تواجه عمليات الاسترجاعات Node.JS مشاكل في التعشيش متعددة الطبقات).
وقت تأخير setTimeout هو 0. غالبًا ما يستخدم هذا الاختراق. الوظيفة التي يطلق عليها SetTimeOut هي في الواقع تجسيد رد الاتصال
استدعاء السلسلة: عند استدعاء السلسلة ، يكون من السهل تنفيذ استدعاء السلسلة في طريقة المقيِّم (Setter) (أو في الأساليب التي لا تُرجع قيمًا) ، ولكن من الصعب نسبيًا تنفيذ Getter القيمة ، لأنك تحتاج إلى إرجاع القيمة التي تحتاجها بدلاً من هذا المؤشر. إذا كنت ترغب في تطبيق طريقة السلسلة ، فيمكنك استخدام وظيفة رد الاتصال لتنفيذها.
تدعو وظيفة SetTimeOut و SetInterval الحصول على قيمة الإرجاع الخاصة بهم. نظرًا لأن كلتا الوظيفتين غير متزامنين ، أي توقيت الاتصالات والعملية الرئيسية للبرنامج مستقلان نسبيًا ، لا توجد وسيلة لانتظار قيمة إرجاعهما في الجسم ، ولن يتوقف البرنامج وينتظر عند فتحهما ، وإلا فإن معنى setTimeOut و setInterval سوف يضيع. لذلك ، لا معنى لها استخدام العودة ، لذلك لا يمكن استخدام رد الاتصال إلا. معنى رد الاتصال هو إخطار وظيفة الوكيل لنتائج تنفيذ المؤقت للمعالجة في الوقت المناسب.
3. الوظائف هي أيضا كائنات
إذا كنت ترغب في فهم وظيفة رد الاتصال ، فيجب عليك أولاً فهم قواعد الوظيفة بوضوح. في JavaScript ، الوظائف غريبة ، لكنها بالفعل كائنات. لكي تكون دقيقًا ، فإن الوظيفة هي كائن دالة تم إنشاؤه باستخدام مُنشئ الدالة (). يحتوي كائن الوظيفة على سلسلة تحتوي على رمز JavaScript للدالة. إذا تم نقلك من C أو Java ، فقد يبدو هذا غريبًا ، كيف يمكن أن يكون الرمز سلسلة؟ ولكن بالنسبة إلى JavaScript ، هذا أمر شائع جدًا. الفرق بين البيانات والرمز غامض.
// يمكن إنشاء الوظيفة بهذه الطريقة var fn = new function ("arg1" ، "arg2" ، "return arg1 * arg2 ؛") ؛ fn (2 ، 3) ؛ // 6تتمثل إحدى الميزات في ذلك في أنه يمكنك تمرير رمز إلى وظائف أخرى ، أو يمكنك تمرير متغيرات أو كائنات منتظمة (لأن الكود حرفيًا مجرد كائن).
وظيفة النقل كإجراء رد اتصال
من السهل تمرير وظيفة كمعلمة.
الدالة fn (arg1 ، arg2 ، callback) {var num = math.ceil (math.random () * (arg1 - arg2) + arg2) ؛ Callback (num) ؛ // تمرير النتيجة} fn (10 ، 20 ، الدالة (num) {console.log ("رد الاتصال! num:" + num) ؛}) ؛ // النتيجة هي رقم عشوائي بين 10 و 20ربما يبدو القيام بذلك مرهقًا وحتى غبي بعض الشيء ، لماذا لا تعيد النتيجة بشكل غير طبيعي؟ ولكن عندما يتعين عليك استخدام وظيفة رد الاتصال ، قد لا تفكر في ذلك!
لا تعترض الطريق
الوظائف التقليدية تدخل البيانات كمعلمات واستخدم عبارات الإرجاع لإرجاع القيم. من الناحية النظرية ، هناك بيان إرجاع في نهاية الوظيفة ، وهو منظم: نقطة إدخال ونقطة الإخراج. هذا أسهل في الفهم. الوظائف هي في الأساس تعيين عملية التنفيذ بين المدخلات والمخرجات.
ومع ذلك ، عندما تكون عملية تنفيذ الوظيفة طويلة جدًا ، هل يجب أن تختار انتظار الوظيفة لإكمال المعالجة ، أو استخدام وظيفة رد الاتصال لأداء المعالجة غير المتزامنة؟ في هذه الحالة ، يصبح استخدام وظائف رد الاتصال أمرًا بالغ الأهمية ، مثل: طلب AJAX. إذا كنت تستخدم وظيفة رد الاتصال للمعالجة ، فيمكن أن يستمر الكود في تنفيذ المهام الأخرى دون إفراغها. في التطوير الفعلي ، غالبًا ما يتم استخدام المكالمات غير المتزامنة في JavaScript ، وينصح بشدة هنا!
فيما يلي مثال أكثر شمولاً على تحميل ملفات XML باستخدام AJAX ، واستخدام وظيفة Call () للاتصال بوظيفة رد الاتصال في سياق الكائن المطلوب.
دالة fn (url ، رد الاتصال) {var httprequest ؛ // إنشاء XHR httprequest = window.xmlhttprequest؟ جديد XMLHTTPREQUEST (): window.activexObject؟ New ActiveXObject ("Microsoft.xmlHttp"): غير محدد ؛ // الكشف الوظيفي لـ IE httprequest.onreadyStateChange = function () {if (httprequest.readystate === 4 && httprequest.status === 200) {// status callback.call (httprequest.responsexml) ؛ }} ؛ httprequest.open ("get" ، url) ؛ httprequest.send () ؛} fn ("text.xml" ، function () {// استدعاء وظيفة console.log (this) ؛ // الإخراج بعد هذا العبارة}) ؛ console.log ("هذا سيتم تشغيله قبل رد الاتصال أعلاه.") ؛ // يخرج هذا البيان أولاًتعني طلباتنا للمعالجة غير المتزامنة أنه عندما نبدأ في الطلب ، نطلب منهم الاتصال بوظيفتنا عند الانتهاء. في المواقف الفعلية ، يجب على معالج الأحداث onReadyStateChange النظر أيضًا في فشل الطلب. هنا نفترض وجود ملف XML ويمكن تحميله بنجاح بواسطة المتصفح. في هذا المثال ، يتم تعيين الوظيفة غير المتزامنة لحدث onReadyStateChange وبالتالي لا يتم تنفيذه على الفور.
أخيرًا ، يتم تنفيذ عبارة Console.log الثانية أولاً ، لأنه لا يتم تنفيذ وظيفة رد الاتصال حتى يتم اكتمال الطلب.
ليس من السهل فهم المثال أعلاه ، لذا ألق نظرة على المثال التالي:
دالة foo () {var a = 10 ؛ الإرجاع دالة () {a *= 2 ؛ إرجاع أ ؛ } ؛ } var f = foo () ؛ f () ؛ // return 20.f () ؛ // العودة 40.تسمى الوظيفة خارجيًا ولا يزال بإمكانها الوصول إلى المتغير أ. هذا كل شيء لأن النطاق في جافا سكريبت هو معجمي. يعمل الوظيفي في النطاق الذي يحددها (النطاق داخل FOO في المثال أعلاه) ، وليس في النطاق الذي يتم فيه تشغيل هذه الوظيفة. طالما تم تعريف F في FOO ، يمكنه الوصول إلى جميع المتغيرات المحددة في FOO ، حتى لو انتهى تنفيذ FOO. لأنه سيتم حفظ نطاقه ، ولكن فقط الوظيفة التي تم إرجاعها يمكنها الوصول إلى النطاق المحفوظ. إن إرجاع وظيفة مجهولة مضمنة هي الطريقة الأكثر شيوعًا لإنشاء عمليات الإغلاق.
ما سبق هو كل شيء عن هذا المقال ، آمل أن يكون من المفيد للجميع تعلم برمجة JavaScript.