التوصيات ذات الصلة: برنامج تعليمي لجافا سكريبت
apply(context,[arguments])
, call(context,param1,param2,...)
.Currying هو أسلوب يحول الدالة التي تقبل معلمات متعددة إلى دالة تقبل معلمة واحدة (المعلمة الأولى للدالة الأصلية)، وتقوم بإرجاع دالة جديدة تقبل المعلمات المتبقية وترجع النتيجة.
على سبيل المثال، إليك دالة add()
، وهي دالة تُستخدم لمعالجة إضافة ومجموع المعلمات (param1، params2،...) التي نمرر إليها.
// هذه هي أول دالة `add(x, y)` ذات معلمتين `x`, `y` function add(x, y){ العودة س + ص؛ } // استدعاء الدالة `add()` وإعطاء معلمتين `4` و`6` إضافة(4,6); // محاكاة عملية الكمبيوتر، قم بتمرير المعلمة الأولى 4 في الخطوة الأولى إضافة وظيفة (4، ص) { العودة 4 + ص؛ } // محاكاة عملية الكمبيوتر، قم بتمرير المعلمة الأولى 6 في الخطوة الثانية إضافة وظيفة (4، 6) { العودة 4 + 6؛ }
كيف سيبدو الأمر لو استخدمنا الدالة add()
؟ فيما يلي تنفيذ بسيط:
// يمكن لوظيفة add () قبول بعض المعلمات function add(x,y){ إذا (نوع ص === 'غير محدد') { وظيفة الإرجاع (جديد) { عودة س + نيوي؛ } } // التطبيق الكامل return x + y; } // اختبار المكالمات console.log(typeof add(4)); // [الوظيفة] console.log(add(4)(6)); // 10 // يمكنك إنشاء وظيفة حفظ Let saveAdd = add(4); console.log(saveAdd(6)); // 10
كما يتبين من وظيفة add()
البسيطة المذكورة أعلاه، يمكن للوظيفة قبول بعض الوظائف ثم إرجاع وظيفة جديدة لمواصلة معالجة الوظائف المتبقية.
نقوم هنا بإنشاء دالة الكاري العامة، حتى لا نضطر إلى تنفيذ عملية الكاري المعقدة بداخلها في كل مرة نكتب فيها دالة.
// تحديد دالة createCurry function createCurry(fn){ شريحة فار = Array.prototype.slice، تخزين_الأرجس = شريحة.call(arguments,1); وظيفة الإرجاع () { دع new_args = شريحة.call(arguments)، args =store_args.concat(new_args); إرجاع fn.apply(null,args); }}
في وظيفة الكاري العامة المذكورة أعلاه:
arguments
ليست مصفوفة حقيقية، ولكنها كائن ذو سمة length
، لذلك نستعير طريقة slice
من Array.prototype
لمساعدتنا في تحويل arguments
إلى مصفوفة حقيقية، لتسهيل عملنا بشكل أفضل.createCurry
لأول مرة، فإن المتغير stored_args
يحمل المعلمات باستثناء المعلمة الأولى، لأن المعلمة الأولى هي الوظيفة التي نحتاج إلى كاريها.createCurry
، يحصل المتغير new_args
على المعلمات ويحولها إلى مصفوفة.stored_args
من خلال الإغلاق وتدمج قيمة المتغير new_args
في مصفوفة جديدة وتعيينها للمتغير args
.fn.apply(null,args)
لتنفيذ الوظيفة المعالجة.الآن دعونا نختبر الدالة العامة
// الدالة العادية add() إضافة وظيفة (س، ص) { العودة س + ص؛ } // احصل على دالة جديدة باستخدام الكاري var newAdd = createCurry(add,4); console.log(newAdd(6)); // 10 // طريقة أخرى بسيطة console.log(createCurry(add,4)(6));// 10
بالطبع، هذا لا يقتصر على معالجة معلمتين، ولكن أيضًا معلمات متعددة:
// معلمات متعددة تضيف الوظيفة العادية (أ، ب، ج، د) { العودة أ + ب + ج + د؛ } // اجمع الدالة للحصول على دالة جديدة، ويمكن تقسيم معلمات متعددة حسب الرغبة console.log(createCurry(add,4,5)(5,6)); // 20 // كاري من خطوتين Let add_one = createCurry(add,5); console.log(add_one(5,5,5));// 20 Let add_two = createCurry(add_one,4,6); console.log(add_two(6)); // 21 من خلال
المثال أعلاه، يمكننا العثور على قيد، أي أنه سواء كان معلمتين أو معلمات متعددة، فلا يمكن تنفيذه إلا في خطوتين، مثل الصيغة التالية:
إذا أردنا أن نكون أكثر مرونة:
;
بعد التمارين المذكورة أعلاه، وجدنا أن الوظيفة الكاري التي أنشأناها لها قيود معينة ونأمل أن يتم تنفيذ الوظيفة في خطوات متعددة:
// إنشاء وظيفة الكاري التي يمكن تنفيذها في خطوات متعددة ، قم بتنفيذه عند استيفاء عدد المعلمات: // صيغة الدالة: fn(x,y,z,w) ==> fn(x)(y)(z)(w); دع createCurry = (fn,...params)=> { Let args = parsms []; Let fnLen = fn.length; // حدد طول المعلمة للوظيفة المعالجة العودة (... الدقة) => { // احصل على جميع المعلمات السابقة من خلال سلسلة النطاق Let allArgs = args.slice(0); // انسخ بعمق معلمات الوسيطات التي تشاركها عمليات الإغلاق لتجنب تأثير العمليات اللاحقة (النوع المرجعي) allArgs.push(...res); إذا (allArgs.length <fnLen){ // عندما يكون عدد المعلمات أقل من طول معلمة الوظيفة الأصلية، قم باستدعاء وظيفة createCurry بشكل متكرر وإرجاع createCurry.call(this,fn,...allArgs); }آخر{ // عند استيفاء عدد المعلمات، يتم إرجاع تنفيذ وظيفة التشغيل fn.apply(this,allArgs); } } } // وظيفة عادية function add(a,b,c,d){ مع معلمات متعددة العودة أ + ب + ج + د؛ } // اختبر وظيفة الكاري Let curryAdd = createCurry(add,1); console.log(curryAdd(2)(3)(4)); //
لقد قمنا بتنفيذ وظائف الكاري المرنة لأكثر من 10 سنوات، ولكن هنا نجد مشكلة أخرى:
curryAdd(add,1,2,3,4)()
;add()
الأصلية. هذه أيضًا إحدى الطرق، ولكن بما أننا نلبي عدد المعلمات هنا، فإننا لا نزال نتعامل مع هذا الموقف.هنا نحتاج فقط إلى إصدار حكم قبل إرجاع الدالة:
Let createCurry = (fn,...params)=> { Let args = parsms []; Let fnLen = fn.length; // حدد طول المعلمة للوظيفة المعالجة إذا (الطول === _args.length){ // أضف حكمًا إذا كان عدد المعلمات لأول مرة كافيًا، فاستدعاء الوظيفة مباشرة للحصول على النتيجة return fn.apply(this,args); } العودة (... الدقة) => { Let allArgs = args.slice(0); allArgs.push(...res); إذا (allArgs.length <fnLen){ إرجاع createCurry.call(this,fn,...allArgs); }آخر{ return fn.apply(this,allArgs); } }}
يمكن اعتبار ما ورد أعلاه وظيفة متجانسة مرنة، ولكنها ليست مرنة جدًا هنا لأنه لا يمكننا التحكم في وقت تنفيذها طالما أن عدد المعلمات كافٍ، فسيتم تنفيذها تلقائيًا. ماذا علينا أن نفعل إذا أردنا تحقيق توقيت يمكن التحكم في تنفيذه؟
دعنا نشرح مباشرة صيغة الدالة هنا:
// عند استيفاء المعلمات، اتصل بالوظيفة Let createCurry = (fn,...params)=> { Let args = parsms []; Let fnLen = fn.length; // حدد طول المعلمة للوظيفة المعالجة // بالطبع يحتاج الحكم هنا إلى التعليق، وإلا فسيتم تنفيذ النتيجة مباشرة عندما يكون عدد المعلمات كافيا لأول مرة //if(length === _args.length){ // أضف حكمًا إذا كان عدد المعلمات لأول مرة كافيًا، فاستدعاء الوظيفة مباشرة للحصول على النتيجة //return fn.apply(this,args); // العودة (... الدقة) => { Let allArgs = args.slice(0); allArgs.push(...res); // هنا يتم الحكم على ما إذا كانت معلمات الإدخال أكبر من 0. وإذا كانت أكبر من 0، يتم الحكم على ما إذا كان عدد المعلمات كافيًا. // لا يمكن استخدام && هنا. إذا تم استخدام &&، فسيتم تنفيذ النتيجة عندما يكون عدد المعلمات كافيًا. إذا (res.length > 0 || allArgs.length < fnLen){ إرجاع createCurry.call(this,fn,...allArgs); }آخر{ return fn.apply(this,allArgs); } } } // وظيفة عادية function add(a,b,c,d){ مع معلمات متعددة العودة أ + ب + ج + د؛ } // اختبر وظيفة الكاري التي يمكن التحكم فيها Let curryAdd = createCurry(add,1); console.log(curryAdd(2)(3)(4)); // وظيفة console.log(curryAdd(2)(3)(4)()); // 10 console.log(curryAdd(2)(3)()); // يُرجع NaN عندما لا تكون المعلمات كافية.
التوصيات ذات الصلة: البرنامج التعليمي لتعلم JavaScript
هو للحديث عن تفاصيل وظيفة JavaScript. يرجى الانتباه إلى مقالات php الأخرى ذات الصلة على الموقع الصيني!