قسمت اول – مفاهیم و الگوهای برنامه نویسی تابعی (Functional) در جاوااسکریپت
فهم، تغییر، استفاده مجدد و نگهداری برنامه و کدهای نوشته شده توسط خود یا دیگران، درد بزرگ مشترک بین برنامه نویسان است و تا به امروز روش ها و الگوی های مختلفی جهت این نیاز و غلبه بر این مشکلات ایجاد شده و برنامه نویسی تابعی یک پارادایم نسبتأ جدید در این خصوص است.
پارادایم در اینجا به این معنی میباشد که برنامه نویسی تابعی یک روش فکر کردن جهت ساخت نرم افزار با پیچیدگی و باگ کمتر و در نتیجه کد تمیز تر، بر اساس چند تعریف پایه ای از جمله فانکشن خالص و تمیز، پرهیز از تغییر وضعیت، پرهیز از ایجاد اثرات جانبی، ترکیب فانکشن ها، پرهیز از به اشتراک گذاری وضعیت ها و غیره است که در ادامه توضیح خواهیم داد.
مثال های دیگر از پاردایم ها نرم افزار، شی گرایی (Object Oriented) و رویهای (Procedural) است (شکل ذیل)
شما اگر واژه برنامه نویسی تابعی یا همان برنامه نویسی فانکشنال را گوگل کنید با مقدار زیادی محتواهای به زبان دانشگاهی روبرو خواهید شد که می تواند به عنوان دیوار برای شما باشد یا ترسناک به نظر برسد اما اگر شما برنامه نویس جاوااسکریپت هستید لذا این شانس را دارید که از مفاهیم و مزایا آن در نرم افزارهایتان به صورت کاربردی استفاده نمایید و ببینید که از آن چه به نظر می رسد آسانتر است.
امروزه در دنیای جاوااسکریپت بیشتر پایه کد های بزرگ از برنامه نویسی تابعی استفاده می کنند و همچنین جهت یادگیری و استفاده بهتر از کتابخانههای مدرن جاوااسکریپت مثل ریاکت، انگولار و یا ویو، برنامه نویسی تابعی و الگوی های مبتنی بر آن یک پیش نیاز مهم و پایهای است.
فانکشن خالص و تمیز (Pure Function)
فانکشنی خالص است، که با ورودی های یکسان نتیجه یکسان برگرداند و باعث اثر جانبی مشهودی نگردد !
یک نمونه فانکشن خالص را در زیر آورده شده است
12345//Pure Function function add (a,b) { return a+b; } add (2,5) //7
فانکش فوق با پارامتر یکسان همیشه نتیجه یکسان بر میگرداند اما فانکش بعدی همیشه با پارامتر یکسان نتیجه مشابه قبلی بر نمی گرداند لذا این نوع فانکش خالص یا Pure نیست و یا اصطلاحأ به آن Impure یا ناخالص می گویند.
12345//Impure Function function (a){ return a * Math.random(); } a(2) // در هر اجرا نتیجه متفاوت بر می گرداند
مثال های دیگر از فانکشن های ناخالص، خواندن یک فایل است و بسته به محتوای فایل خروجی فانکشن در هر خواندن تغییر می نماید و همانطور که در بالا گفتیم فانکشنی خالص است که علاوه بر نتیجه یکسان و با پارامتر یکسان ، باعث اثر جانبی نگردد مانند اثر جانبی که تغییر یک شی یا متغییر عمومی و یا فرستادن یک پارامتر با Reference است را شامل می شود، به مثال زیر توجه کنید:
123456let counter = 1; function increaseCounter (value) { counter = value + 1; } increaseCounter(counter); console.log(counter); // 2
همانطور که می بینید متغییر counter یک متغییر عمومی برای فانکش نا خالص increaseCounter است و مقدار آن در فانکشن مذکور تغییر پیدا کرده و در هر جای برنامه که از این متغییر استفاده شود مقدار آن افزایش میابد و با تغییر آن باعث اثر جانبی می گردد که ممکن است منجر به اثرات مخرب و ایجاد پیچیدگی گردد.
لذا بهتر است کد فوق را به صورت زیر نوشته شود.
1234let counter = 1; const increaseCounter = (value) => value + 1; increaseCounter(counter); // 2 console.log(counter); // 1
همانطور که می بینید ما در فانکش خالص increaseCounter مقدار افزایش یافته را داریم اما باعث هیچ اثر جانبی نگردیده است و متغییر عمومی counter را تغییر نداده است.
همانطور که می بینید با همین دو قانون ساده کد ما خوانا تر گردیده و هر فانکشن ایزوله شده و به سادگی قابل تست است و تأثیری بروی سایر بخش های برنامه نمیگذارد.
نکته : فانکشن یک مقدار است.
یک نکته کلیدی که در کد فوق استفاده شده، این است که در برنامه نویسی تابعی فانکش یک مقدار است ! و شما نمی توانید در سایر برنامه نویسی های غیر تابعی این کد را بنویسید.
const increaseCounter = (value) => value + 1;
ما نتیجه یک فانکش را به صورت یک مقدار داریم بنام increaseCounter و این بسیار مهم است و ما میتوانیم مانند مقدار با یک فانکشن برخورد کنیم و به عنوان مثال ما می توانیم یک فانکشن را به عنوان یک مقدار به یک فانکشن دیگر به عنوان پارامتر ارسال کنیم .
در ادامه به این قابلیت بسیار مهم و کاربردی بر می گردیم .
در اینجا قسمت اول را تمام می کنیم و در قسمت های بعدی درباره مفاهیم دیگر برنامه نویسی تابعی و الگوی های آن صحبت خواهیم کرد.