برنامه نویسی با کلوژر

Closure در جاوا اسکریپت چیست؟ توضیح کلوژر به زبان ساده + مثال و کد فرادرس مجله‌

در این مطلب از «مجله فرادرس» به زبان ساده این پرسش را پاسخ می‌دهیم که Closure در جاوا اسکریپت چیست و برای درک بهتر این مفهوم، مثال‌هایی نیز به همراه کدهای مربوطه ارائه شده‌اند. یکی از مفاهیم مهمی که در جاوا اسکریپت وجود دارد و قصد داریم در این مقاله به بررسی آن بپردازیم، “کلوژر‌ها” هستند. کلوژر چیزی نیست جز یک تابع معمولی که داخل یک تابع دیگه تعریف و برگشت داده میشه (return میشه). به عبارتی هنگامی که یک تابع مقدار یک متغیر تعریف شده خارج از اون رو میخونه یا ویرایش میکنه، یک کلوژر داریم. در کد مثال قبلی، وقتی آرایه functionsArray ایجاد شد، هر یک از توابع بی‌نامی که در این آرایه ذخیره شده بودند، به متغیر i اشاره می‌کردند. مهم است که متوجه شویم که این توابع، مقدار i را به خاطر نمی‌سپارند، بلکه به متغیری که در حوزهٔ تابع بیرونی تعریف شده است، اشاره می‌کنند.

از طرف دیگر در دامنه استاتیک myVarرا به متغیری که در محدوده دو تابع «IIFE» در هنگام ایجاد ذخیره شده بود، بازیابی می‌کند. محدوه داینامیک اغلب ابهام ایجاد خواهد کرد، زیرا مشخص نیست که متغیر آزاد از کدام محدوده بازیابی می‌شود. زبان‌های دارای دامنه پویا، مانند زبان‌هایی که پیاده‌سازی‌های مبتنی بر پشته دارند، متغیرهای محلی و آرگومان‌های تابع را در پشته ذخیره می‌کنند. وضعیت فعلی پشته برنامه تعیین می‌کند که کدام متغیر در زمانی معین ارجاع داده می‌شود. در جاوا اسکریپت، مفهوم «دامنه یا محدوده» (Scope) ارتباط نزدیکی با تودرتویی سلسله مراتبی محیط‌های واژگانی دارد و از پیش‌نیازهای درک و یادگیری مفهوم Closure یا بستار در جاوا اسکریپت است. هنگامی که یک متغیر یا تابعی مورد دسترسی قرار می‌گیرد، جاوا اسکریپت ابتدا در حوزه فعلی به دنبال آن می‌گردد.

حداقل اثبات شده که تمام ریاضیات و استدلالها رو میشه به وسیلۀ حساب لاندا (با قواعد واقعاً سادش) به طور خیلی دقیق بیان کرد. مسیرهای دیگری مثل نویسندگی، آموزش یا هنرهای دیجیتال را نیز امتحان کنید و از تجربیات خود، مثل تقویت تفکر منطقی و حل مسئله، در انتخاب‌های جدید بهره بگیرید. در نهایت، با بازگشت به علایق اصلی‌تان و مشورت با افراد حرفه‌ای، مسیری را انتخاب کنید که بیشترین رضایت و رشد را برایتان به ارمغان بیاورد. اگر آدمی هستید که سریع ناامید می‌شوید یا حوصله زیادی برای بررسی دقیق جزئیات ندارید، شاید کار در زمینه برنامه‌‌نویسی برای شما چالش‌برانگیز باشد. اما اگر از تلاش و پیشرفت لذت می‌برید، این ویژگی به شما کمک می‌کند تا به یک برنامه‌نویس موفق تبدیل شوید.

متغیر count که در محدوده تابع wonderfulFunction تعریف شده و در داخل تابع counter نیز قابل استفاده و در دسترس است. یادگیری مفهوم کلوژر (Closure) در جاوا اسکریپت (JavaScript) گیج کننده به نظر می رسد زیرا درک نحوه کار آن واقعا دشوار است. در یک برنامه وب، بسیاری از اجزاء مختلف، نیازمند به اشتراک گذاری داده و ارتباط با یکدیگر دارند. متغیرها و توابعی که درون یک تابع یا بلوک کد تعریف می‌شوند، در حوزه محلی قرار دارند و فقط درون آن تابع یا بلوک قابل دسترسی هستند. متغیرها و توابعی که در بیرون از هر تابع یا بلوک کد تعریف می‌شوند، در حوزه سراسری قرار دارند و در سراسر برنامه قابل دسترسی هستند. چرخه حیات در جاوااسکریپت شامل مراحلی است که در طول اجرای یک برنامه رخ می‌دهند.

گسترش (Extend) نام دیتاتایپ را به دنبال هر شماره از نقشه پروتکل یا روش می‌گیرد. منظور از نقشه یک نقشه معمولی از نام متدها است که به‌عنوان کلمات کلیدی به پیاده‌سازی آنها داده می‌شود. وقتی می‌خواهید چندین پروتکل را برای یک دیتاتایپ اجرا کنید از extension-type و برای اجرای همان پروتکل در چندین دیتاتایپ از extend-protocol استفاده کنید. فرض کنید برنامه‌ای وجود دارد که شما در آن قادر به تغییر کد منبع نیستید. در این حالت برای ایجاد یک پروتکل جدید که روی دیتاتایپ موجود عمل کند باید پروتکل‌ها را گسترش دهید. مزیت ۷- یک دیتاتایپ‌ (datatype) برای ارائه پیاده‌سازی به هیچ روش، پروتکل یا اینترفیسی نیاز ندارد.

احتمالا تا الان بدون اینکه بدانید در توسعه برنامه های خود از کلوژرها استفاده کرده اید. اما آشنایی با کلوژرها و نحوه عملکرد آنها راه حل های جدیدی در توسعه برنامه ارائه می دهد. Currying یک الگوی طراحی (و مشخصه ویژه برخی از زبان ها) است که در آن یک تابع بلافاصله ارزیابی می شود و یک تابع دومی را برگشت می دهد. امکان استفاده از متغیرهای private که فقط توسط خود ماژول در داخل تابع قابل استفاده می باشند را فراهم می کند. یک تابع می تواند به مقادیر تعریف شده خارج از بدنه تابع دسترسی پیدا کند (مانند مثال قبل). خب الان فرض کنید در سند Js پروژتون یک متغیری تحت عنوان y تعریف کردید و تعریف این متغیر شما داخل هیچ حلقه، شرط و فانکشنی انجام نشده.

کلوژرها یکی از مفاهیمی است که درک آن هنگام شروع کار سخت خواهد بود اما اگر آنها را هنگام استفاده تشخیص دهید و درک کنید، گزینه های بیشتری در دسترس خواهید داشت و حرفه ای تر عمل خواهید کرد. IIFE یا فراخوانی سریع توابع روشی است که در ES5 برای پیاده سازی الگوی طراحی “ماژول” خیلی استفاده می شد. ایده این است که ماژول در تابعی بسته بندی می شود که بلافاصله اجرا خواهد شد. این “اثر” داشتن کلوژرها است و دلیلش اینه که جاوا اسکریپت از توابع تودرتو پشتیبانی می کند. به عبارت دیگر کلوژرها first class citizens هستند و می توانید از آنها مانند هر شی دیگری استفاده کنید. پس از بستن و تمام شدن اجرای تابع wonderfulFunction، همه متغیرها و تابع های تعریف شده در بدنه آن “ناپدید می شوند”.

این مراحل شامل ایجاد، استفاده و از بین بردن متغیرها، توابع و اشیاء می‌شود. آبجکت یا Object در جاوا اسکریپت یک ساختار داده‌ای است که به شما اجازه می‌دهد مجموعه‌ای از خواص (properties) و مقادیر (values) را ذخیره و مدیریت کنید. هر property یک کلید (key) و یک مقدار (value) دارد، که کلیدها معمولاً رشته‌ها هستند و مقادیر می‌توانند هر نوع داده‌ای باشند، از جمله اعداد، رشته‌ها، توابع و حتی دیگر آبجکت‌ها. آبجکت‌ها به شما این امکان را می‌دهند که داده‌های مرتبط را به صورت ساختاریافته و منظم سازمان‌دهی کنید. پروتوتایپ (Prototype) در جاوا اسکریپت یک مکانیزم است که به اشیاء امکان می‌دهد ویژگی‌ها و متدها را از یک شیء دیگر به ارث ببرند.

این نه تنها در مورد توابع، بلکه در مورد سایر ساختارهای کد مانند دستورات بلوک یا عبارات catch نیز صدق می‌کند. با این حال، برای سادگی، در طول این بحث بر روی محیط‌هایی که به وسیله توابع ایجاد می‌شوند تمرکز خواهیم کرد. وقتی تابعی تعریف می‌شود، هر متغیری در آن تابع فقط در خود تابع قابل دسترسی است. تلاش برای دسترسی به این متغیرها از خارج از تابع منجر به خطای دامنه یا محدوده می‌شود. حالا چی داریم؟ تابع counter که از مقدار متغیر count تعریف شده خارج از تابع استفاده می کند.

به‌عبارت‌دیگر، خاصیت چند روشی در کلوژر، تمام استدلال‌ها را به خواص دلخواه شما ارسال می‌‌کند. مشکل اساسی توسعه‌پذیری، دست‌کاری دیتاتایپ‌ها به‌وسیله عملیات‌ انجام‌شده در برنامه‌ها است. همان‌طور که برنامه‌ها در حال تکامل هستند باید عملیات و دیتاتایپ‌های ‌جدید، گسترش پیدا کنند. نکته مهم این است که برنامه‌نویس باید بتواند عملیات جدیدی را که با انواع دیتاتایپ‌های موجود کار می‌کند و داده‌های جدیدی که با انواع عملیات‌ موجود کار می‌کنند به برنامه‌اش اضافه کند. منظور ما، یک گسترش واقعی است یعنی گسترشی که در آن برنامه موجود، اصلاح نشود. مزیت ۶- تفاوت مهم بین پروتکل‌ها و اینترفیس‌ها در این است که پروتکل‌ها هیچ ارثی ندارند.

هنگامی‌که نمونه‌هایی از آن دیتاتایپ را فراخوانی می‌کنید، فقدان روش‌ها باعث پیاده‌سازی AbstractMethodError می‌شود. این دوره فرصت‌های زیادی را برای کار در یک بازار خاص باز می‌کند، جایی که مهارت‌های شما برای کارفرمایان بسیار ارزشمند خواهد بود. کمبود زیادی در مهارت های Clojure وجود دارد، و شما می توانید رتبه اول را کسب کنید. بسیاری از بازیکنان بزرگ مانند LinkedIn، Cisco، CitiGroup و غیره از Clojure به عنوان یکی از زبان‌های اصلی خود استفاده می‌کنند. تصویر زیر از صفحه مربوط به کدهای بالا در کنسول مرورگر در ادامه آمده است. Event یا رویداد کاربرد نوعی دیگر از کلوژرها در event handlers یا کنترل کننده های رویداد با استفاده از React است.

اما شاید براتون سوال پیش بیاد که کلوژر چه مزایایی داره و اصلا تعریف کردن یه تابع داخل یه تابع دیگه چه کاربردی داره؟! در پاسخ به این سوال میشه گفت که این کار، امنیت و پایداری اطلاعات رو برای ما تامین میکنه و هر وقت به اطلاعاتی پایدار و امن نیاز داشتیم، میتونیم از کلوژر‌ها کمک بگیریم. یکی از کاربردهای رایج اون‌ها، مربوط به event handlers برای تعاملات کاربر است. با تعریف توابع به عنوان کلوژرها، توسعه‌ دهندگان میتونند اون‌ها رو به راحتی نگهداری و  به‌روز‌‌رسانی کنند. این رویکرد همچنین امکان ایجاد قابلیت‌های پیچیده‌تری مانند انیمیشن‌های سفارشی یا ویجت‌های تعاملی رو  نیز فراهم میکنه. تا این قسمت از مقاله آموزش Closure در جاوا اسکریپت با دو مفهوم global scope و local scope آشنا شدیم، حالا بریم یه مثال خوب ببینیم.

با داشتن ارجاع به محیط تابع MysteriousCalculator، متدهای addو subtractمی‌توانند به متغیرهای موجود در آن محیط (a ,b ,mysteriousVariable) برای انجام محاسبات خود دسترسی داشته باشند. به طور خلاصه، محیط واژگانی نقشی حیاتی در ایجاد ارتباط و معنای شناسه‌ها در کد دارد. این شامل نوعی رکورد محیطی برای ثبت پیوندهای شناسه و نوعی ساختار تو در توی سلسله مراتبی است که امکان زنجیره‌بندی محیط‌های واژگانی را فراهم می‌کند. در کدهای فوق، هنگامی که اجرای تابع boop کامل شد، از بالای پشته حذف می‌شود. در نتیجه، تابع bar از سر گرفته شده و جای خود را به عنوان زمینه اجرای در حال اجرا، تثبیت می‌کند که تصویر زیر مربوط به این مورد است.

هر شیء در جاوااسکریپت یک پروتوتایپ دارد، که در واقع یک شیء دیگر است و می‌توان ویژگی‌ها و متدهای مشترک را در آن تعریف کرد. Clojure یک زبان برنامه نویسی کاربردی با هدف کلی، الهام گرفته از جاوا است. هر حرفه‌ای مزایا و معایب خاص خود را دارد و برنامه‌نویسی نیز از این قاعده مستثنا نیست. اگر به فکر ورود به دنیای برنامه‌نویسی هستید، آگاهی از جنبه‌های مثبت و منفی آن می‌تواند به شما کمک کند تصمیم بهتری بگیرید. در این بخش، مزایا و معایب برنامه‌نویسی را به صورت کامل و خلاصه بررسی می‌کنیم تا دیدی شفاف‌تر از این مسیر به دست آورید.

به عبارت دیگر، inner دسترسی به متغیرهای حوزهٔ تابع بیرونی خود را حتی پس از پایان اجرای آن تابع حفظ می‌کند. این خاصیت به عنوان حوزهٔ واژگانی (lexical scoping) شناخته می‌شود و یکی از ویژگی‌های مهم و قدرتمند در جاوااسکریپت است. اکثر زبان‌های مرسوم، ویژگی‌های پایه‌ای هم‌روندی، یعنی ریسمان‌ها و قفل‌ها را در اختیار می‌گذارند. داستان من با دنیای برنامه‌ نویسی آغاز شد، و در ادامه به عنوان یک توسعه‌ دهنده نرم‌ افزار، طراح وب سایت و متخصص سئو، مهارت ‌های تکنیکی و تحلیلی خودم رو پرورش دادم. علاقه م به دنیای مالی منو به سمت یادگیری ترید و معامله‌گری سوق داد. و در حال حاضر در برنامه نویسی و معامله گری ارز دیجیتال انجام میدم.از سال 96 سعی کردم معامله گری در کریپتو رو یاد بگیرم.

به این معنی که هر تابع بی‌نام در آرایه، مرجع متغیر i را نگه می‌دارد. برای شروع، زبان‌های ساده و پرکاربرد مثل Python یا JavaScript گزینه‌های خوبی هستند. اگر به توسعه وب علاقه دارید، تکنولوژی هایی مثل HTML، CSS، و JavaScript شروع خوبی است. اگر به تحلیل داده‌ها و هوش مصنوعی علاقه‌مندید، Python می‌تواند بهترین گزینه باشد. در مثال فوق، تابع secretPassword شیئی را با متد guessPassword برمی‌گرداند. متغیر password در محدوده تابع secretPasswordتعریف شده است و مستقیماً از خارج قابل دسترسی نیست.

این فیلم آموزشی به زبان انگلیسی ساده و روان تدریس شده است که امید است مورد توجه شما عزیزان علاقه مند به برنامه نویسی قرار بگیرد. کلوژر (Clojure) گویشی از زبان برنامه نویسی لیسپ (Lisp) است که توسط ریچ هیکی (Rich Hickey) ایجادشده است. کد کلوژر به بایت‌کد (Bytecode) ماشین مجازی جاوا (Java Virtual Machine, JVM) کامپایل می‌شود. «بستار» (Closure) نوعی ویژگی بسیار تاثیرگذار است که در جاوا اسکریپت و همچنین بسیاری از زبان‌های برنامه نویسی دیگر یافت می‌شود. طبق تعریف ارائه شده به وسیله «MDN»، کلوژرها توابعی هستند که به متغیرهای مستقل ارجاع می‌دهند. به عبارت دیگر در جاوا اسکریپت، Closure‌ها به عنوان شکلی از «تعیین محدوده واژگانی» (Lexical scoping) برای حفظ متغیرها از محدوده بیرونی تابع در محدوده درونی آن استفاده می‌شوند.

بهترین راه برای یافتن پاسخ، تجربه عملی با پروژه‌های کوچک و منابع آموزشی است. به یاد داشته باشید، چه برنامه‌نویسی را انتخاب کنید یا مسیر دیگری را، مهم این است که با اشتیاق و علاقه پیش بروید. در قطعه کد بالا وقتی تابع test فراخوانی می‌شود، مقدار بازگشتی 45 را بازیابی می‌کند. این به این دلیل است که تابع testتابع bar را فراخوانی خواهد کرد که حتی پس از بازگشت تابع foo به متغیر آزاد y دسترسی دارد. تابع barدسترسی به y را به وسیله محیط بیرونی خود که محیط foo است حفظ می‌کند. علاوه بر این، تابع barمی‌تواند به متغیر جهانی x دسترسی داشته باشد، زیرا محیط fooبه محیط جهانی دسترسی دارد.

زمینه اجرای فعلی همیشه در بالای پشته قرار دارد و تا زمانی که کدهای درون آن ارزیابی شود در این موقعیت باقی می‌ماند. پس از ارزیابی، زمینه اجرایی فعلی از پشته خارج می‌شود و به آیتم بعدی اجازه می‌دهد تا به زمینه اجرای فعلی (در حال اجرا) تبدیل شود. همچنین قبل از اینکه زمینه اجرای دیگری تصاحب شود، نیازی به تکمیل زمینه اجرای در حال اجرا نیست. شرایطی وجود دارد که زمینه اجرایی در حال اجرا به طور موقت به حالت تعلیق در می‌آید و نوعی زمینه اجرایی متفاوت دیگر به زمینه در حال اجرای جدید تبدیل می‌شود. خود متغیر helloبعد از تابع ناشناس در همان تابع محصور اعلان می‌شود.

برای پیشرفت و عمیق شدن در مفهوم Closure در جاوا اسکریپت، مهم است که کاربران به طور فعال آنچه را که آموخته‌اند به کار ببرند و تمرین کنند. Closure می‌تواند مفهومی چالش برانگیز باشد، بنابراین اختصاص زمان برای تحقیق و تمرین Closure در سناریوهای مختلف، درک کاربر را بسیار افزایش می‌دهد. کاربران با به دست آوردن تجربه عملی، درک عمیق‌تری از نحوه عملکرد Closure در جاوا اسکریپت و کاربردهای عملی آن خواهند داشت. در حالی که رویکرد IIFE می‌تواند در سناریوهای خاصی موثر باشد، شایان ذکر است که راه‌حل «ES6» با استفاده از let راه‌حل تمیزتر و مختصرتری برای مشکل ذکر شده ارائه می‌دهد. کلمه کلیدی let به طور خودکار محدوده بلوک را ایجاد می‌کند و در بیشتر موارد نیاز به IIFE را از بین می‌برد. با این حال، ممکن است شرایطی وجود داشته باشد که رویکرد IIFE بهتر باشد که بحث در مورد آن بسیار تخصصی است.

یعنی اگه کاربر هی تغییر اندازه بده، تابع اجرا نمیشه و فقط وقتی که تغییرات متوقف بشه، تابع اصلی اجرا میشه. کلوژرها برای کنترل تعداد دفعات اجرای تابع توی تکنیک های دیبانس (debounce) و ثروتلینگ (throttling) استفاده میشن. این تکنیک ها کمک میکنن که توابعی که به دفعات زیاد صدا زده میشن (مثل رویدادهای اسکرول یا تایپ) محدود بشن و فقط در زمان های مشخصی اجرا بشن. کلوژرها با نگهداشتن وضعیت و زمان آخرین اجرا، این کنترل رو ممکن میکنن. در علوم رایانه و ارتباطات، پروتکل (Protocol) عبارت است از استاندارد یا قراردادی که برای ارتباط میان دو گروه، برقرار می‌شود. پروتکل در ساده‌ترین حالت می‌تواند به‌عنوان قوانین اداره منطق، ترکیب و همزمانی ارتباطات در نظر گرفته شود.

در ادامه ٣ مثال از مفهوم Closure در جاوا اسکریپت برای درک بهتر مفاهیم بیان شده رائه می‌شود. در مثال فوق، مشاهده می‌شود که دامنه استاتیک و داینامیک نتایج متفاوتی را هنگام فراخوانی تابع bar به دست می‌دهند. با دامنه ایستا، مقدار بازگشتی barبر اساس مقدار x در زمان ایجاد foo است. این به دلیل ساختار ایستا و واژگانی کد منبع است که برای xدر آغاز 10 و در نتیجه 15 خواهد بود. برای درک بهتر مفهوم Execution Context در جاوا اسکریپت در ادامه مثالی ارائه شده است. مفهوم زمینه اجرا یا «Execution Context» نوعی مفهوم انتزاعی است که به وسیله مشخصات «ECMAScript» برای ردیابی ارزیابی زمان اجرای کدها مورد استفاده می‌گیرد.


برنامه نویسی لوا