Masoud Mirzaei
Masoud Mirzaei
خواندن ۳ دقیقه·۶ سال پیش

دنباله دار کردن تابع ها در JavaScript یا Function Currying

امروز وقتی داشتم برای یه مصاحبه کاری توی انگلیس تست فنی می دادم، یه سوالی خیلی مشغولم کرد و بعد از ۳۰ دقیقه و فقط وقتی ۲۹ ثانیه وقت به پایان مونده بود موفق شدم جواب درستش رو بنویسم.

سوال میگه می خوایم یک تابع داشته باشیم که میشه به صورت دنباله دار صداش زد. تابع ما در واقع یک سری عدد رو به عنوان ورودی قبول می کنه و در نهایت قراره که جمع همه این اعداد رو به ما برگردونه.


تست کیس ما همچین چیزیه: جمع اعداد ۱ تا ۵ که میشه ۱۵.

add(1)(2)(3)(4)(5).result() // must return 15

در نهایت کد ما به صورت بالا استفاده میشه، اما این امکان هم هست که ما رشته تابع add رو موقتا بندازیم توی یک متغیر و بعدا اگر دلمون خواست از طریق متد result نتیجه جمع شون رو چاپ کنیم. اینطوری:

var sum1 = add(1)(2); var sum2 = add(3)(4)(5); var sumFinal = sum1.result() + sum2.result();

قبل از اینکه از چه جوری انجامش رو بگم ببینید می تونید خودتون از پسش بر بیاین؟!


خوب حالا که خیلی کنجکاوی میریم سراغ روش انجامش! کاری که اینجا ما می خوایم انجام بدیم رو بهش می گن Function Currying.

چیزی که خیلی واضحه اینه که ما هر باری که داریم متوالی add رو صدا می کنیم در واقع داریم مجددا همون تابع رو صدا می کنیم. تابعی که واسمون جمع زدن رو انجام میده درسته!؟

اما ما داریم به صورت متمادی هم اینکارو می کنیم پس ما یه متغیری هم باید داشته باشیم که جمع زدن هامون رو توش انجام میدیم.

بزارید بهتون نشون بدم منظورم چیه:

// Define add function function add(x) { // let's define a variable to keep the numbers we add let sum = x; // now we need to define a function that we return every time after first invokes function resultFn(y) { // Add the numbers we take after the first time to the one we first kept! sum += y; // And return resultFn to make it possible we call it afterwards return resultFn; } // We haven't been returning the results! so let's do that // Lets add a method to the resultFn we've developed to return the current sum // whenever it's invoked resultFn.result = function () { return sum; } return resultFn; }

اما توضیحاتش:

ما یه تابع داریم به اسم add. توی این تابع فقط و فقط دفعه اولی که صدا زده میشه ما اولین عددی که میگیریم رو میندازیم توی یه متغیری به اسم sum. این sum رو بعدا استفاده می کنیم تا عدد های بعدی رو توش جمع بزنیم. حالا میایم یه تابع جدید تعریف می کنیم به اسم resultFn که اونم توی خود add هست و قراره از این به بعد اونو برگردونیم و صدا بزنیم و دیگه خود add رو کاری نداریم. چرا؟‌ چون می خوایم بتونیم add رو اینطوری صدا بزنیم:

add(1)(2)...(n)

توی resultFn ما میایم عدد جدیدمون رو که حالا با y نشونش میدیم به اون sum قبلی اضافه می کنیم! باید دقت کنیم که sum ما از اون بار اول دست نخورده مگر اینکه توی resultFn تغییرش بدیم!

پس در واقع از بار دوم به بعد هر باری که ما یه پرانتز اضافه می کنیم داریم resultFn رو صدا می کنیم نه add. و در نهایت از اونجایی که چیزی که برگشته resultFn هست، ما یک متد بهش اضافه کردیم که sum ما که توی closure تابع add ثابت مونده رو بهمون برمیگردونه.

حالا آزمایشش کنیم:

add(1)(2)(3)(4)(5).result() // returns 15


var sum1 = add(1)(2); // returns resultFn var sum2 = add(3)(4)(5); // returns resultFn var sumFinal = sum1.result() + sum2.result(); // returns 15


حالا یه خورده فکرتونو به کار بندازین ببینین می تونید همینکارو واسه ضرب هم انجام بدین؟!



در مورد function currying بخونید. چیزی که خیلی با method chaining متفاوته ولی به درد بخور. جاوا اسکریپت دنیای جالبی داره و اینم امروز چلنج جالبی بود که بهش برخوردم.

دنبال چیزای خفن باشین و همیشه کنجکاو باشین ✌?


javascriptfunction
شاید از این پست‌ها خوشتان بیاید