مفهوم IIFE و Closure در جاوا اسکریپت و Nested Functions

جاوا اسکریپت پره از ارورهایی که خیلی موقعا دردسرای بزرگی رو توی پروژه‌ها ایجاد میکنه. اما یه سری قوانین میتونن به کمکمون بیان تا به جای handle اون ارور با روش‌های غیر منطقی و کد کثیف، خیلی راحت درک و از ریشه حلشون کنیم. توی این پست میخوایم یکی از اون مشکلات و روش handleش رو یاد بگیریم :)

خیلی وقتا نیاز داریم که توی functionمون، یه function دیگه داشته ‌باشیم تا بتونیم از دیتاهای موجود استفاده کنیم. روش خیلی خوبیه برای این که سمت تعریف متغیر global یا setState و ... نریم. اما ممکنه این کارمون منجر به ارورهایی بشه که توی این متن با این ارورها و handleکردنشون آشنا میشیم!

اول کار رو با یه مثال شروع می‌کنم. به نظرتون با call کردن تابع f، چه خروجی‌ای خواهیم‌داشت؟ (قبل از خوندن ادامه متن، حتما روش فکر کنین)

خروجی f به نظر شما چیه؟
خروجی f به نظر شما چیه؟




جواب: undefined!

و اما علتش چیزی میشه که ما رو میرسونه به مفهوم خیلی مهمی به اسم Closure. نقل قول زیر میتونه درجه اهمیتش رو برسونه:

Coding in JavaScript without an understanding of closures is like trying to speak English without an understanding of grammar rules

اگر بخوام خیلی کوتاه و ساده تعریف کنم، باید بگم که closureها هستن که به ما اجازه دسترسی از inner function به outer function میدن. این رو هم یادتون باشه که توی JavaScript، بلافاصله بعد از ساخته‌شدن تابع، closure هم ساخته میشه.

توی تیکه کد بالا، وقتی وارد scope توی function اصلی(wrapElements) میشیم، برای هر variable که result و i و n هستند، یه slot توی memory اختصاص داده میشه (allocate)

و مشکل از جایی شروع میشه که ما وارد حلقه for میشیم. وقتی وارد این حلقه میشیم، خیلیامون انتظار داریم که خود value از i رو داشته‌باشیم. در حالی که ما فقط و فقط یک reference از i داریم و دیگر هیچ!

پس یادمون باشه که:

Closures store their outer variables by reference, not by value

علت undefinedگرفتنمون حالا معلوم میشه: این که functionهای داخلی، منتظر میمونن تا آخرین مقدار Closure براشون فرستاده بشه. یعنی توی این تیکه کد، توی حلقه for، تابع صدا زده نمیشه تا وقتی که i به عدد 5 که مقدار نهایی هست میرسه. و اینجاست که میخواد توی آرایه با ایندکس‌های 0 تا 4، دنبال ایندکس 5 بگرده و به undefined میخوره :)

حالا فرض کنید var i رو اون بالا تعریف نکنیم و بیاریمش تو scope پایینی و همونجایی که قراره استفادش کنیم. پس کد ما این شکلی میشه:

جالبه بدونید که اینجا هم undefined میخوریم!

و علتش هم اینه که وقتی ما توی scopeهای پایینی، متغیری رو تعریف می‌کنیم، دقیقا مثل اینه که اون بالا تعریفش کردیم و این پایین ازش استفاده میکنیم! پس بار دیگه، فقط و فقط یه slot توی مموری برای i خواهیم داشت. دقیقا مثل تیکه کد اولمون.

پس با ارور آشنا شدیم :) چجوری هندلش کنیم؟

جوابش ما رو میرسونه به عنوان بحثمون یعنی Immediately Invoked Function Expression

این تیکه کد رو خوب نگاه کنید!

استفاده از تکنیک IIFE
استفاده از تکنیک IIFE

این تکنیک توی هر تغییر i، یه function میسازه و بلافاصله صداش میزنه. و اینجاست که آرایه result با هر تغییر i، یه عضو جدید درست میکنه. خوبه که اسم اصلی اینجور تعریف توابع رو هم بدونیم: Self-invoking functions

و دیگه ارور undefined رو نخواهیم‌ داشت?

پس به همین راحتی و با خوندن چند کتاب خوب از جاوا اسکریپت، میتونیم این مشکلا رو از ریشه متوجه بشیم تا این ارورها و handleکردن غیرمنطقیشون، بعدا باعث شکل‌گیری فاجعه توی پروژه نشه

موفق و سربلند باشید❤ Reza Hasani