آموزش Closure در جاوا اسکریپت
کلوژرها، یکی از پرکاربردترین تکنیکها در جاوا اسکریپت هستند. یادگیری کلوژرها بیشتر از این که یادگیری یک مفهوم جدید باشد، تشخیص زمان استفاده آن است. کلوژر به برنامهنویس جاوا اسکریپت این امکان رو میده که سریعتر، خلاقانهتر و کاربردیتر کدنویسی انجام بده. آموزش جاوا اسکریپت
کلوژرها مقدمهای بر جاوا اسکریپت
امروزه احتمالا نام جاوا اسکریپت را زیاد شنیده باشید! همانطور که ممکن است بدانید، جاوا اسکریپت یک زبان برنامه نویسی مهم است که برای طراحان و توسعهدهندگان وب، ابزاری ضروری تلقی میشود. این زبان اسکریپتیِ سمت کاربر، در مرورگر اجرا میشود و به توسعهدهندگان امکان ایجاد صفحات تعاملی و پویا را میدهد.
جاوا اسکریپت در طراحی وب به شیوههای مختلفی استفاده میشود، از اعتبارسنجی فرمها بگیرید تا انیمیشن، ویجت، افکت و کلی امکان جالب توجه دیگه که به آنها اشاره نکردیم!
Scope چیست؟
برای بررسی مبحث Closure در جاوا اسکریپت ابتدا باید مبحثی به نام Scope را بررسی کنیم.
مبحث Scope فقط به جاوا اسکریپت محدود نمی شود و در بقیه زبان ها نیز مطرح هست.
شما وقتی در یک زبان برنامه نویسی (که اینجا منظور جاوا اسکریپت است) متغیری تعریف می کنید، اون متغیر در یک ناحیه مشخص و معین قابل استفاده است و خارج از محدوده تعیین شده نمی شود از آن متغیر استفاده کرد، حتی برای نمایش محتوای متغیر.
به عنوان مثال اگر متغیری تحت عنوان x در یک فانکشن(تابع) تعریف کنید، نمی توانید خارج از فانکشن به متغیر x دسترسی داشته باشید. برای درک بهتر به کد زیر دقت کنید:
function showX () { var x = 10 console.log(x) } showX() // 10 console.log(x) // Error
همان طور که در کد بالا مشاهده می کنید، با کال کردن(فراخوانی) فانکشن showX مقدار متغیر x برای کاربر log گرفته می شود اما موقع استفاده از متغیر x خارج از فانکشن showX، بهمون خطای undefined داده و این به این معنی هست که متغیر x در خط 7 ناشناخته هست. در این تکه کد scope یا همان منطقه استفاده متغیر x فقط داخل فانکشن showX است و خارج از showX به هیچ وجه نمی توان از متغیر x استفاده کرد.
در این قسمت به ناحیه متغیر x ناحیه local گفته می شود(local scope).
این فقط یک مثال برای local scope بود که شما با این موضوع آشنا بشوید و ناحیه های local دیگری مثل حلقه for نیز وجود دارند.
خب این از loal scope، بریم ببینیم scope دیگه ای هم وجود داره یا نه
Global Scope
خب الان فرض کنید در سند Js پروژتون یک متغیری تحت عنوان y تعریف کردید و تعریف این متغیر شما داخل هیچ حلقه، شرط و فانکشنی انجام نشده.
به دلیل این که متغیر y داخل هیچ ناحیه ای تعریف نشده و به هیچ ناحیه ای محدود نیست، یک متغیر global (سراسری) محسوب می شود که scope آن global نامیده می شود(global scope). متغیر y شما می تواند در سر تا سر سند Js پروژه شما قابل استفاده باشد.
شما می توانید از متغیر y داخل تمامی فانکشن ها، حلقه ها، شرط ها و … استفاده کنین.
برای درک بهتر این موضوع به کد زیر دقت کنید:
var y = 20 function showY () { console.log(y) } showY() // 20 console.log(y) // 20
همان طور که در کد بالا مشاهده می کنید، با وجود این که متغیر y خارج از فانکشن showY تعریف شده، اما داخل فانکشن (ناحیه showY) نیز قابل استفاده است. در این قسمت ناحیه متغیر y
سراسری (global) است که در اصطلاح global scope گفته می شود.
تا این قسمت از مقاله آموزش Closure در جاوا اسکریپت با دو مفهوم global scope و local scope آشنا شدیم، حالا بریم یه مثال خوب ببینیم.
یه مثال خوب
خب فرض کنید قصد دارید یک متغیر تحت عنوان counter با مقدار اولیه 1 و یک فانکشن با اسم addCounter داشته باشید که وظیفه فانکشن افزایش یک واحد به متغیر counter باشد:
var counter = 0 function addCounter () { counter++ console.log(counter) } console.log(counter) // 0 addCounter() // 1 addCounter() // 2 console.log(counter) // 2
همان طور که در تکه کد بالا مشاهده می کنید، با وجود این که متغیر counter در خارج از فانکشن addCounter تعریف شده، داخل addCounter نیز می توانیم از counter استفاده کنیم و مقدار آن را تغییر دهیم.
با توجه به کد بالا برنامه ما بدون هیچ خطایی کار می کند و عملکرد مورد نظر ما (افزایش یک واحدی متغیر counter) رو به راحتی انجام می دهد.
اما با توجه به خط های 8 و 11 در خارج از فانکشن نیز قابل استفاده است و حتی می توان خارج از فانکشن نیز مقدار آن را تغییر داد، چون متغیر y در global scope تعریف شده است.
این مورد که متغیر counter خارج از فانکشن نیز قابل استفاده است امنیت متغیر را پایین می آورد. اگر بخواهیم متغیر counter خارج از فانکشن قابل دسترسی نباشد باید چه کاری انجام داد؟
شاید بگید باید متغیر رو داخل addCounter تعریف کنیم تا فقط در ناحیه addCounter در دسترس باشد؛ بریم ببینیم با این راه حل مشکلمون برطرف میشه یا نه.
خب همون طور که گفتیم یه راه حل میتونه این باشه که متغیر counter رو داخل addCounter تعریف کنیم تا در خارج از آن در دسترس نباشد:
function addCounter () { var counter = 0 counter++ console.log(counter) } // console.log(counter) // Error addCounter() // 1 addCounter() // 1 addCounter() // 1 console.log(counter) // Error
خب خب…
همان طور که در کد بالا مشاهده می کنید به دلیل این که متغیر counter به صورت local تعریف شده و فقط به ناحیه فانکشن addCounter محدود است، با هر دفعه کال کردن این فانکشن کد های آن اجرا می شوند؛
پس با هر دفعه اجرای فانکشن متغیر counter یک بار با مقدار اولیه 0 تعریف میشود، مقدار آن ++ می شود و سپس log گرفته می شود و به این ترتیب با هر تعداد فراخوانی فانکشن addCounter مقدار متغیر counter همچنان 1 خواهد بود.
همچنین که در خط های 7 و 11 مشاهده می کنید، در خارج از فانکشن نمی توانیم به متغیر counter دسترسی داشته باشیم. پس این روش تا حدی امنیت متغیر مورد نظر ما رو تامین کرد اما نتوانست عملکرد مورد نظر ما رو به درستی انجام بده (افزایش مقدار counter) و با هر تعداد فراخوانی فانکشن، مقدار متغیر counter همچنان 1 می باشد.
خب حالا راه حل این چیه؟ الان بریم سراغ خود Closure
کلوژر در جاوا اسکریپت
یکی از مفاهیم مهمی که در جاوا اسکریپت وجود دارد و قصد داریم در این مقاله به بررسی آن بپردازیم، “کلوژرها” هستند. کلوژر یکی از چندین ویژگی قدرتمند زبان جاوا اسکریپت است. کلوژر چیزی نیست جز یک تابع معمولی که داخل یک تابع دیگه تعریف و برگشت داده میشه (return میشه). به عبارتی هنگامی که یک تابع مقدار یک متغیر تعریف شده خارج از اون رو میخونه یا ویرایش میکنه، یک کلوژر داریم.
کلوژر اساساً یک تابع درونی است که حتی پس از اتمام اجرای تابع والد به محدوده تابع والد دسترسی دارد. این کار با ایجاد یک تابع در یک تابع دیگر انجام میشود.
تابع
کلوژر
حوزه متغیر
کلوژرها سه سطح دسترسی دارند :
1. دسترسی به حوزه یا محدوده خودش
2. دسترسی به متغیرهای توابع خارجی
3. دسترسی به متغیرهای global
در ادامه با بررسی یک مثال این موضوع را بهتر بررسی و درک میکنیم.
کلوژر در طراحی وب
در طراحی وب، کلوژرها میتونند به شیوههای مختلفی استفاده شوند. یکی از کاربردهای رایج اونها، مربوط به event handlers برای تعاملات کاربر است. با تعریف توابع به عنوان کلوژرها، توسعه دهندگان میتونند اونها رو به راحتی نگهداری و بهروزرسانی کنند. این رویکرد همچنین امکان ایجاد قابلیتهای پیچیدهتری مانند انیمیشنهای سفارشی یا ویجتهای تعاملی رو نیز فراهم میکنه.
کلوژرها همچنین برای مدیریت وضعیت در برنامههای وب مفید هستند. در یک برنامه وب، بسیاری از اجزاء مختلف، نیازمند به اشتراک گذاری داده و ارتباط با یکدیگر دارند. با استفاده از کلوژرها برای تعریف توابع و اشیاء، توسعه دهندگان میتونند یک کد سازمان یافته و ماژولار ایجاد کنند که مدیریت وضعیت را بهبود، امنیت همان قطعه کد را بالا و جلوگیری از خطا را آسانتر کند.
مزایای کلوژر
اما شاید براتون سوال پیش بیاد که کلوژر چه مزایایی داره و اصلا تعریف کردن یه تابع داخل یه تابع دیگه چه کاربردی داره؟! در پاسخ به این سوال میشه گفت که این کار، امنیت و پایداری اطلاعات رو برای ما تامین میکنه و هر وقت به اطلاعاتی پایدار و امن نیاز داشتیم، میتونیم از کلوژرها کمک بگیریم.
خب مبحث Closure اومده تا این مشکل ما رو برطرف کنه. در صورت کلی Closure فانکشنی هست که داخل یک فانکشن دیگه تعریف و return میشه.
خب الان بریم عملکرد مد نظرمون رو با Closure بنویسیم و نتیجه رو ببینیم.
function makeAdd() { var counter = 0; function addCounter() { counter++; console.log(counter) } return addCounter; } var plusCounter = makeAdd() plusCounter() plusCounter() plusCounter()
خب خب …
داخل فانکشن makeAdd یک فانکشن دیگه addCounter رو return کردیم؛
پس با هر دفعه اجرای فانکشن makeAdd، فانکشن addCounter را برای ما برمیگرداند و ما به addCounter دسترسی داریم.
از طرفی چون که متغیر counter داخل فانکشن makeAdd تعریف شده است، فقط داخل همین فانکشن در دسترس است و addCounter نیز به آن دسترسی دارد.
خروجی فانکشن makeAdd را که همان فانکشن addCounter است داخل متغیری به اسم plusCounter ذخیره می کنیم.
حالا مقدار متغیر plusCounter همان فانکشن addCounter می باشد. با اجرای هر دفعه plusCounter (یا همان addCounter) یک واحد به متغیر counter اضافه شده و آن لاگ گرفته می شود و به این ترتیب در هر دفعه اجرای آن مقادیر 1، 2 و 3 لاگ گرفته می شوند.
به این ترتیب Closure مشکل های موجود رو حل کرد و عملکرد مورد نظر ما به درستی اجرا شد.
در مورد Clusure به کد زیر هم دقت کنید:
function makeLog () { return function getLog () { console.log('Log') } } makeLog()() // Log makeLog()() // Log makeLog()() // Log
یک کوژر می تواند به این صورت هم قابل استفاده باشد. شما با پرانتز اولی فانکشن والد رو کال کرده و با پرانتز دومی کلوژری که return میشه رو کال می کنید.
سخن پایانی
شاید تا الان بدون اینکه خودتون بدونید در توسعه برنامههاتون از کلوژرها استفاده کردهاید. اما آشنایی با کلوژرها و نحوه عملکرد اونها راه حلهای جدیدی در توسعه برنامه ارائه میده. کلوژرها یکی از مفاهیمی هستند که درک اون هنگام شروع کار سخت خواهد بود اما اگر اونها رو هنگام استفاده تشخیص بدید و درک کنید، گزینههای بیشتری در دسترس خواهید داشت و حرفهای تر عمل خواهید کرد. اگر میخواید بیشتر با کلوژرها آشنا بشید و بهتر درکش کنید، حتما به دوره آموزش جاوا اسکریپت سبزلرن یه سر بزنید. قطعا کارتون رو راه میندازه!
امیدوارم مطالب این مقاله براتون مفید بوده باشه. خوشحال میشم نظراتتون رو در مورد این مقاله بدونم.
🔥