بسته شدن در جاوا اسکریپت چگونه کار می کند؟ با مثال کد توضیح داده شده است
سالی و جو دو پرنده عشق هستند. آنها همه چیز را با یکدیگر به اشتراک گذاشتند و به زودی تقریباً غیرممکن بود که فکر کنیم چیزی بین آنها وجود دارد. یک روز، آنها دعوا کردند که منجر به جدایی شد.
برای جو سخت بود و او خواهان "بستن" بود. اگرچه سالی پیش از این حرکت کرده بود، اما جو با صرف زمان برای فکر کردن در کل تجربه، یادآوری «خاطرات مشترک» و درون نگری مناسب به پایان رسید. با وجود اینکه این رابطه به پایان رسیده بود، جو هنوز چیزی داشت که او را به یاد سالی می انداخت و او با این حرف خونسرد بود.
داستان به پایان می رسد.
اگر این اولین بار است که اصطلاح "بسته شدن" را می شنوید، افتخار می کنم که معنی آن را به شما بگویم.
بسته شدن صرفاً عمل به پایان رساندن چیزی است. بسته شدن در یک رابطه به احساس آرامش و درک شما پس از پایان رابطه اشاره دارد. این همان احساس "رها کردن" و توانایی ادامه دادن است.
برای برخی از افراد، بستن شامل نگه داشتن یک "خاطره مشترک" با طرف مقابل یا چیزی (شاید یک مورد) است که آنها را به یاد طرف مقابل می اندازد.
اکنون که با اصطلاح بسته شدن آشنا شدید همانطور که به انسان مربوط می شود، بیایید سعی کنیم آن را از نظر رابطه بین توابع در جاوا اسکریپت درک کنیم.
در جاوا اسکریپت، بسته شدن زمانی ایجاد می شود که یک تابع دسترسی به منابع (های) اعلام شده در محدوده والد خود را حتی پس از حذف تابع والد از پشته تماس حفظ کند.
نکته : در جاوا اسکریپت، وقتی گفته میشود تابعی از پشته پاپآف/حذف شده است، به این معنی است که طول عمر آن تابع به پایان رسیده است (در حال اجرا است) و تمام منابع آن از حافظه حذف شده است و دیگر در دسترس نیست
به پشته تماس مانند دنیا فکر کنید، در حالی که والدین و فرزند دو موجودیت در جهان هستند.
در این حالت، parent
تابعی است که اجرا را به پایان رسانده است و منطقاً همه چیز در مورد آن باید دور از دسترس باشد اما به دلیل مفهوم بسته شدن، حتی زمانی که رابطه بین توابع parent
و child
به پایان رسیده است. یعنی وقتی والدین از پشته بیرون میآیند (از دنیا حذف میشوند)، تابع فرزند هنوز همه چیزهایی را که با هم به اشتراک گذاشتهاند به خاطر میآورد.
توجه : هر چیزی که آنها با هم به اشتراک گذاشتند همانطور که در بالا استفاده شد به سادگی به معنی متغیرهای اعلام شده در تابع parent
است که توسط تابع child
استفاده می شود.
function parent () { let a = "Az"; return function child () { console.log(a); } }
در قطعه کد بالا، متغیر a
چیزی است که توابع parent
و child
با هم به اشتراک می گذارند.
پس حتی زمانی که parent
از پشته تماس حذف می شود، child
هنوز مقدار a
را به خاطر می آورد تا زمانی که زنده است
اگر در این مرحله مطالعه را متوقف کنید، از قبل میدانید که بسته شدن از نظر مفهومی چیست، اما اگر میخواهید آن را به طور کامل درک کنید و هرگز فراموش نکنید، باید به عمق عملکرد جاوا اسکریپت بپردازیم.
فرو رفتن عمیق در مفهوم بسته شدن.
برای درک واقعی بسته شدن در جاوا اسکریپت، باید با مفاهیم زیر آشنا باشید:
توابع را می توان به عنوان مقادیر به متغیرها اختصاص داد
const getName = function () { return 'Allice' };
اکنون میتوانید به سادگی تابع getName
درست مانند هر تابع دیگری با استفاده از پرانتز مانند getName()
فراخوانی کنید.
توابع را به عنوان اشیاء فراخوانی در نظر بگیرید. این بدان معناست که دقیقاً همانطور که میتوانیم اشیاء را به متغیرها اختصاص دهیم و آنها را منتقل کنیم، شما میتوانید همین کار را با توابع انجام دهید. تفاوت بین آنها این است که می توانید زمانی که برای اجرا به کد موجود در آن نیاز دارید، یک تابع را فراخوانی کنید.
توابع را می توان به عنوان آرگومان به توابع دیگر منتقل کرد
setTimeout(getName, 5000)
همانطور که در قطعه کد بالا مشاهده می کنید، در حین فراخوانی تابع setTimeout
، تابع getName
را به عنوان آرگومان به آن ارسال کردیم. باز هم به این دلیل است که توابع به سادگی اشیایی هستند که قابل فراخوانی هستند.
توجه داشته باشید که وقتی تابع getName
به تابع setTimeout
میدهیم، آن را فراخوانی نمیکنیم. ما به سادگی تابع را به عنوان یک مقدار منتقل می کنیم.
اگر تابع را فراخوانی میکردیم، به جای آن مقدار بازگشتی آن را ارسال میکردیم و این تفاوت قابل توجهی است.
من همچنین می خواهم به شما توجه کنم که ذکر نام یک تابع به سادگی ارجاع به آن تابع است. در پشت صحنه، نام تابع با خود تابع جایگزین می شود.
یعنی این کد setTimeout(getName, 5000)
معادل کد زیر است.
setTimeout(function () { return 'Allice' }, 5000)
نام تابع در حین اجرا با خود تابع جایگزین می شود درست مانند نام متغیر معمولی که در حین اجرا با مقدار آن جایگزین می شود.
توابع را می توان از توابع دیگر برگرداند.
function multiplyBy (numberToMultiplyBy) { return function (numberToMultiply) { return numberToMultiply * numberToMultiplyBy } }
با نگاهی دقیق به قطعه کد بالا، متوجه خواهید شد که ما تابعی به نام multiplyBy
داریم که در حین فراخوانی، یک آرگومان را انتظار دارد و یک تابع جدید برمی گرداند.
نکته جالب توجه در اینجا این است که وقتی تابع برگردانده شده را فراخوانی می کنیم، انتظار آرگومان نیز دارد، اما این بار، آرگومان ارسال شده به تابع
اصلی ( multiplyBy
numberToMultiplyBy
) را به خاطر می آورد، سپس مقدار ارسال شده در خود ( numberToMultiply
) را ضرب می کند. مقدار به تابع والد خود ارسال می شود و نتیجه را برمی گرداند.
کد زیر را با دقت مشاهده کنید که از تابع مرتبه بالاتر multiplyBy
استفاده می کند:
const multiplyByTwo = multiplyBy(2) const result = multiplyByTwo(8) console.log(result) // 16
2. مفهوم توابع مرتبه بالاتر: این دومین مفهومی است که برای درک بسته شدن باید از آن آگاه باشید.
تابع مرتبه بالاتر تابعی است که:
تابعی را به عنوان آرگومان می پذیرد. به عنوان مثال: setTimeout
، Promise
و غیره.
تابعی را برمیگرداند. به عنوان مثال: تابع multiplyBy
اعلام شده در بالا.
یا موارد اول و دوم بالا را برآورده می کند.
اکنون که متوجه شدید که توابع شهروندان درجه یک هستند و اجرای یک تابع درجه بالاتر را مشاهده کرده اید، می توانیم در مورد بسته شدن صحبت کنیم.
به یاد داشته باشید که بسته شدن زمانی اتفاق میافتد که یک تابع فرزند یک مقدار یا منبعی را که به تابع والد خود تعلق دارد، ارجاع میدهد/به خاطر میآورد، حتی پس از حذف تابع والد از پشته فراخوانی.
function sally () { let age = 64; return function joe () { const data = { name: "Joe", parentName: "Sally", parentAge: age } return data } }
در قطعه کد بالا می توانیم مشاهده کنیم که:
sally
تابع والد است و یک محدوده را اعلام می کند
age
متغیری است که در محدوده sally
اعلام شده است
joe
تابعی است که در محدوده sally
زندگی می کند و توسط تابع sally
برگردانده می شود. همچنین باید توجه داشته باشید که:
- joe
محدوده خود را تعریف می کند که یک محدوده کودک است را sally
محدوده
- در محدوده joe
، به age
متغیری که متعلق به دامنه sally
است اشاره می کنیم (این جایی است که بسته شدن اتفاق میافتد زیرا joe
به منبع/متغیری اشاره میکند یا آن را نگه میدارد که متعلق به sally
است).
از آنجایی که joe
ارجاعی به متغیر age
دارد که به sally
تعلق دارد، حتی زمانی که sally
از پشته تماس خارج شده و دامنه آن کنار گذاشته شده است، joe
به دلیل مفهوم بسته شدن، دسترسی به متغیر age
را حفظ خواهد کرد.
پس در کد زیر:
const joe = sally() // sally is invoked and returns the joe function const joeyData = joe() // joe function is invoked and returns an object console.log(joeyData) // we log the object returned.
میتوانید مشاهده کنید که حتی اگر sally
فراخوانی میشود و از پشته بیرون میآید، وقتی joe
فراخوانی میکنید و مقدار بازگشتی joe
به کنسول وارد میکنید، همچنان age
سالی را در طول اجرا به یاد میآورد (که میتوانیم در شیء برگشتی به آن دسترسی پیدا کنیم. مانند joeyData.parentAge
).
خلاصه
هنگامی که یک تابع فرزند به متغیرهای استفاده شده در محدوده والد خود اشاره می کند، بسته شدن اتفاق می افتد.
بسته شدن مانند یک جعبه حافظه است که تمام موارد حوزه والد را که از دامنه فرزند به آنها ارجاع می شود، ذخیره می کند.
نگاهی به اسلایدهای زیر باید دانشی را که تا کنون به دست آوردهاید تقویت کند و امیدواریم همه چیز سر جای خود قرار گیرد.
بسته ها باز شده است؟ مهارتهای جاوا اسکریپت خود را با آموزشهای توسعه کاملتر در کانال YouTube من افزایش دهید. اکنون برای فهرست پخش بعدی من در مورد مفاهیم اساسی جاوا اسکریپت مشترک شوید!
با تشکر برای خواندن! کد نویسی مبارک!
ارسال نظر