
وفقًا لبعض الاستطلاعات ، تعد وظائف الأسهم المجهولة في JavaScript هي الميزة الأكثر شيوعًا في ES-2015 ، والتي يتم التأكيد عليها أيضًا من خلال العدد الشامل من البرامج التعليمية على الإنترنت. إنها مفيدة للغاية بلا شك ، ولكن في هذه المقالة القصيرة سنلقي نظرة على أمثلة لاستخدام الحرمان من الانتباه على الأقل تعبيرات رائعة مع وظائف مسماة - NFE.
مساعدة قصيرة
Named Function Expression - امتداد للتعبيرات الوظيفية في JavaScript يسمح لك بتسمية دالة تم إنشاؤها كجزء من تعبير ( FunctionExpression ):
let fe = function named(...) { };
النقطة الأساسية هي أنه داخل الدالة المشار إليها بواسطة المتغير fe ، هناك وصول إلى الوظيفة نفسها من خلال الاسم المسمى . من المستحيل إعادة كتابة الاسم فقط من داخل الوظيفة!
كيفية استخدامه
على سبيل المثال ، نحتاج إلى كتابة وظيفة تزيين تحسب عدد المكالمات لبعض الوظائف. يمكن القيام بذلك بأناقة مع NFE:
const count = f => function df() { df.calls = (df.calls || 0) + 1; return f(...arguments); };
هنا وصلنا إلى وظيفة df التي تم إرجاعها ، بحيث عندما يتم استدعاؤها ، نقوم بحفظ العداد في خاصية المكالمات ، والتي ستكون متاحة للقراءة إذا لزم الأمر:
const csum = count((x, y) => x + y); csum(5, 10);
أو احفظ جميع نتائج استدعاء الوظيفة:
const accum = f => function df() { let res = f(...arguments); (df.results = (df.results || [])).push(res); return res; };
على أي حال ، نحن نستفيد من حقيقة أن الوظيفة في JavaScript هي كائن ، ويمكننا تكميلها بالخصائص الضرورية في مهامنا المحلية.
من الواضح أنه يمكننا استدعاء دالة. يعد استخدام NFE للرجوع أمرًا رائعًا بشكل خاص. افترض أننا نريد العثور على العضو التاسع في تسلسل فيبوناتشي (لسبب ما ، يريد الجميع ذلك عاجلاً أم آجلاً):
const rf = function getfn(n) { return n > 2 ? getfn(n - 2) + getfn(n - 1) : 1; }; rf(1);
لا يستحق الانتباه إلى "المخلفات" هنا. ولكن على القدرة على القيام بالشيء نفسه من خلال إعلان الوظيفة - نعم. ولكن وظيفة التعبير لها ميزة واحدة: إذا كنت ترغب في نقل الوظيفة من rf إلى متغير آخر ، فلن تحتاج إلى تحرير المكالمة العودية في الداخل.
مثال أنيق على تنفيذ المؤقت:
const ping = (callback, t) => setTimeout(function pf() { callback(); setTimeout(pf, t); }, t);
هنا نستخدم NFE كحرف كحجة بدلاً من التصريح عن متغير غير ضروري. لماذا لا تحدد إنترفال ؟ بدلاً من إعادة الاتصال ، قد يكون هناك انتظار لقرار الوعد قبل العلامة التالية للمؤقت.
مثال مثير للاهتمام هو الجمع بين NFE و IIFE ( التعبير عن الوظيفة التي يتم استدعاؤها على الفور ) ، عندما تكون هناك حاجة فقط نتيجة الدالة العودية. مرة واحدة فقط:
let data = { f10: function fact(n) { return n > 1 ? n * fact(n - 1) : 1; }(10) }; data.f10;
هل هذا صحيح؟ حسنًا ، إليك المشكلة الحقيقية: هناك بعض الوظائف المتزايدة بشكل صارم f التي تعمل في مجموعة الأعداد الطبيعية. أوجد النقطة المتطرفة x التي لا تتجاوز عندها قيمة التابع y . مثال على هذه الوظيفة سيكون f(x) = 3 * x + 5
أو f(x) = 2^x + 11
.
const find = (f, y) => function bs(a, b) { if (a + 1 === b) return a; let m = Math.ceil((a + b) / 2); return f(m) <= y ? bs(m, b) : bs(a, m); }(-1, y + 1); find(x => 3 * x + 5, 200);
لن ندخل في التفاصيل الرياضية. النظر في التنفيذ:
- تحتوي دالة البحث المطلوبة على معلمتين f و y وتعرض نتيجة IIFE.
- تطبق وظيفة تسمى على الفور بحثًا ثنائيًا عن حل ، تحصل المكالمة الأولى على النطاق الأولي.
- يتم تنفيذ البحث نفسه من خلال العودية ، والذي يستخدم اسم NFE للمكالمات اللاحقة. لا نعلن وظيفة بحث ولا ننشئ متغيرًا جديدًا.
بالطبع ، يمكن حل مشكلة مماثلة من خلال دورة بسيطة مع شرط مسبق ، ولكن هذا أمر ضروري للغاية لتشفير وحدة التحكم.
أخيرًا ، بضع كلمات حول تتبع المكدس. لدينا بعض وظائف NFE ، التي تم طرح استثناء في نصها:
const fe = function named() { throw new Error('Something went wrong'); };
نظرًا لأن لدينا وظيفة مسماة في التعبير ، فسوف نراها في تتبع المكدس:
Uncaught Error: Something went wrong at named (<anonymous>:2:11)
ومع ذلك ، بدءًا من ES-2015 ، تقوم العديد من تعبيرات الدوال المجهولة في الواقع بإنشاء دالة باسم ، وإخراجها من السياق:
const unnamed = function() { throw new Error('Something went wrong'); };
ترتبط الوظيفة على الجانب الأيمن من التعبير بالمتغير على اليسار:
Uncaught Error: Something went wrong at unnamed (<anonymous>:2:7)
لكن هذا ليس ممكنًا دائمًا. مثال كلاسيكي هو تهيئة برنامج نصي خارجي للمكتبة من خلال IIFE ، كخيار:
;(function() {
أو مثال متكرر لدالة تُرجع دالة أخرى:
const bind = (f, ctx) => function() { return f.apply(ctx, arguments); };
لا يوجد متغير للإخراج ، لذلك في حالة وجود استثناء سنرى مجهول . قد تساعد NFE قليلاً في التقاضي.
استنتاج قصير
تعد NFE جيدة في كتابة تعليمات برمجية موجزة وغير مدعومة لوضع نموذج سريع لمجموعة كبيرة من المهام. لاستخدام جمالها في الشفرة النهائية ، يجب أن تفكر عدة مرات: جافا سكريبت محملة بالفعل بمواصفات مثيرة للاهتمام.