أصول الكاري واسم عالم الرياضيات Haskell Curry (تم تسمية لغة البرمجة Haskell أيضًا باسمه).
يسمى الكاري أيضًا التقييم الجزئي. معناها هو تمرير المعلمات إلى وظيفة خطوة بخطوة. بعد تمرير كل معلمة ، قم بتطبيق المعلمات جزئيًا ، وإرجاع وظيفة أكثر تحديدًا لقبول المعلمات المتبقية. يمكن أن تتداخل طبقات متعددة من وظائف المعلمة الجزئية في الوسط حتى يتم إرجاع النتيجة النهائية.
لذلك ، فإن عملية الكاري هي عملية لتمرير المعلمات تدريجياً ، وتضيق تدريجياً نطاق تطبيق الوظائف ، وحلها تدريجياً.
كاري وظيفة مجموع
بعد التقييم خطوة بخطوة ، دعونا نلقي نظرة على مثال بسيط
var concat3words = function (a ، b ، c) {return a+b+c ؛ } ؛ var concat3wordscurrying = function (a) {return function (b) {return function (c) {return a+b+c ؛ } ؛ } ؛ } ؛ console.log (concat3words ("foo" ، "bar" ، "baza")) ؛ // foo bar baza console.log (concat3wordscurrying ("foo")) ؛ // [function] console.log (concat3wordscurrying ("foo") ("bar") ("baza")) ؛ // Foo Bar Bazaكما ترون ، فإن concat3wordscurrying ("foo") هي وظيفة ، كل مكالمة تُرجع وظيفة جديدة ، تقبل مكالمة أخرى ، ثم تُرجع وظيفة جديدة حتى يتم إرجاع النتيجة أخيرًا ، ويتم حل التوزيع ، ويتقدم الطبقة حسب الطبقة. (PS: يتم الاستفادة من خصائص الإغلاق هنا)
حتى الآن نذهب إلى أبعد من ذلك. إذا كنا بحاجة إلى تمرير أكثر من 3 معلمات ، فيمكننا تمرير أكبر عدد ممكن من المعلمات وإخراج النتيجة عند عدم تمرير المعلمات؟
أولاً ، دعونا نتلقى تنفيذًا طبيعيًا:
var add = function (items) {return items.reduce (function (a ، b) {return a+b}) ؛ } ؛ console.log (إضافة ([1،2،3،4])) ؛ولكن إذا طلبت مضاعفة كل رقم بنسبة 10 ثم أضفته ، ثم:
var add = function (العناصر ، multi) {items.map (function (item) {return item*multi ؛}). تقليل (function (a ، b) {return a + b}) ؛ } ؛ console.log (إضافة ([1 ، 2 ، 3 ، 4] ، 10)) ؛لحسن الحظ ، هناك خريطة وتقليل الوظائف. إذا اتبعنا هذا النمط ، نحتاج إلى إضافة 1 إلى كل عنصر وتلخيصه ، فعندئذ نحتاج إلى استبدال الوظائف الموجودة في الخريطة.
دعونا نلقي نظرة على تطبيق الكاري:
var adder = function () {var _args = [] ؛ Return Function () {if (mancepitions.length === 0) {return _args.reduce (function (a ، b) {return a + b ؛}) ؛ } [] .push.apply (_args ، [] .slice.call (الوسيطات)) ؛ إرجاع الحجج. }} ؛ var sum = adder () ؛ console.log (sum) ؛ // وظيفة SUM (100200) (300) ؛ // تنسيق المكالمات مرن ، يمكن إدخال معلمة واحدة أو أكثر في وقت واحد ، ويدعم استدعاء السلسلة إلى SUM (400) ؛ console.log (sum ()) ؛ // 1000 (حساب إجمالي)Adder أعلاه عبارة عن وظيفة على شكل كاري ، والتي تُرجع وظيفة جديدة ، ويمكن أن تقبل الوظيفة الجديدة معلمات جديدة على دفعات ، وتأخير حتى آخر عملية حسابية.
وظيفة الكاري العامة
سيؤدي الكاري الأكثر نموذجية إلى تغليف الحساب الأخير في وظيفة ، ثم تمرير هذه الوظيفة كمعلمة في وظيفة الكاري ، وهي واضحة ومرنة.
على سبيل المثال ، اضرب كل مصطلح في 10 ، يمكننا تمرير وظيفة المعالجة كمعلمة:
var currying = function (fn) {var _args = [] ؛ الإرجاع دالة () {if (mancepitions.length === 0) {return fn.apply (this ، _args) ؛ } array.prototype.push.apply (_args ، [] .slice.call (الوسيطات)) ؛ إرجاع الحجج. }} ؛ var multi = function () {var total = 0 ؛ لـ (var i = 0 ، c ؛ c = الوسائط [i ++] ؛) {total+= c ؛ } إجمالي الإرجاع ؛ } ؛ var sum = currying (multi) ؛ مجموع (100200) (300) ؛ مجموع (400) ؛ console.log (sum ()) ؛ // 1000 (يتم حسابه فقط عند مكالمات فارغة)وبهذه الطريقة ، sum = currying (multi) ، فإن المكالمة واضحة للغاية ، وتأثير الاستخدام رائع أيضًا. على سبيل المثال ، لتجميع قيم متعددة ، يمكنك استخدام قيم متعددة كمعلمات SUM (1،2،3) ، أو مكالمات سلسلة الدعم ، Sum (1) (2) (3)
أساس الكاري
الرمز أعلاه هو في الواقع وظيفة عالية الترتيب. تشير وظيفة الترتيب العالي إلى وظيفة تدير وظيفة. يتلقى وظيفة واحدة أو أكثر كمعلمات وإرجاع وظيفة جديدة. بالإضافة إلى ذلك ، يتم الاعتماد على خصائص الإغلاق أيضًا لحفظ المعلمات التي تم إدخالها في العملية الوسيطة. الآن:
يمكن تمرير الوظائف كمعلمات
يمكن استخدام الوظائف كقيمة إرجاع للوظيفة
إنهاء
دور الكاري
حساب التأخير. المثال أعلاه منخفض نسبيا.
المعلمة تعدد الإرسال. عندما تسمى نفس الوظيفة عدة مرات ، تكون المعلمات التي تم تمريرها هي نفسها في الغالب ، ثم قد تكون الوظيفة مرشحًا جيدًا للكاري.
إنشاء وظائف ديناميكيا. يمكن إنشاء هذا ديناميكيًا بعد نتائج الحساب الجزئي ، على هذا الأساس ، يتم إنشاء وظيفة جديدة ديناميكيًا لمعالجة الأعمال اللاحقة ، وبالتالي حذف الحسابات المتكررة. أو يمكنك إنشاء وظيفة جديدة ديناميكيًا عن طريق تطبيق جزء من المجموعة الفرعية من المعلمات المراد نقلها إلى وظيفة الاتصال ، والتي توفر المعلمات التي تم تمريرها بشكل متكرر (ليس بالضرورة في كل مرة في المستقبل). على سبيل المثال ، طريقة مساعدة لمتصفحات الأحداث لإضافة الأحداث:
var addEvent = function (el ، type ، fn ، capture) {if (window.adDeventListener) {el.addeventListener (type ، function (e) {fn.call (el ، e) ؛} ، capture) ؛ } if if (window.attachevent) {el.attachevent ("on" + type ، function (e) {fn.call (el ، e) ؛}) ؛ }} ؛في كل مرة تضيف فيها حدثًا ، يجب عليك التنفيذ إذا ... آخر .... في الواقع ، في متصفح ، تحتاج فقط إلى اتخاذ قرار مرة واحدة. يمكنك إنشاء وظيفة جديدة بشكل ديناميكي بناءً على النتيجة بعد الحكم ، وليس هناك حاجة لإعادة حسابها في المستقبل.
var addEvent = (function () {if (window.addeventListener) {function function (el ، stype ، fn ، capture) {el.addeventListener (stype ، function (e) {fn.call (el ، e) ؛} ، (capture)) ؛} ؛ el.attachevent ("on" + stype ، function (e) {fn.call (EL ،هذا المثال ، بعد الحكم الأول لـ IF ... Else ... ، يتم الانتهاء من جزء من الحساب ، ويتم إنشاء وظيفة جديدة ديناميكيًا لمعالجة المعلمات التي تم تمريرها لاحقًا. هذا هو الكاري النموذجي.
طريقة function.prototype.bind هي أيضًا تطبيق الكاري
بخلاف طريقة الاتصال/تطبيقها التي تنفذ مباشرة ، تقوم طريقة BIND بتعيين المعلمة الأولى على سياق تنفيذ الوظيفة ، ويتم تمرير المعلمات الأخرى إلى طريقة الاتصال بدورها (لا يتم تنفيذ جسم الوظيفة نفسها ، والتي يمكن اعتبارها تأخير تنفيذ) ، وينشئ ديناميكيًا وإرجاع وظيفة جديدة ، والتي تتوافق مع خصائص الكذبة.
var foo = {x: 888} ؛ var bar = function () {console.log (this.x) ؛ } .bind (foo) ؛ // BIND BAR () ؛ // 888فيما يلي محاكاة وظيفة ربط. Testbind ينشئ وإرجاع وظيفة جديدة. في الوظيفة الجديدة ، ترتبط الوظيفة التي تريد تنفيذ العمل حقًا بالسياق الذي تم تمريره في المعلمة الفعلية ، ويتأخر التنفيذ.
function.prototype.testbind = function (scope) {var fn = this ؛ //// هذا يشير إلى دالة تستدعي طريقة testbind ، FRORT FUNCTION () {return fn.apply (SCOPE) ؛ }} ؛ var testbindbar = bar.testbind (foo) ؛ // bind Foo لتأخير تنفيذ console.log (testbindbar) ؛ // وظيفة (انظر ، بعد الربط ، إرجاع وظيفة جديدة تؤخر التنفيذ) TestBindbar () ؛ // 888هنا يجب أن نولي اهتمامًا لفهم هذا في النموذج الأولي.
المقالة أعلاه تحليل متعمق للوظائف التي تتجه إلى كاري جافا سكريبت هي كل المحتوى الذي أشاركه معك. آمل أن تتمكن من إعطائك مرجعًا وآمل أن تتمكن من دعم wulin.com أكثر.