بستن JS مدارهای جاوا اسکریپت: مثال عملی، ویژگی ها و قوانین

سلام همه! در این مقاله ما به آن نگاه خواهیم کرد بسته شدن جاوا اسکریپت چیست؟.

این یک موضوع بسیار ساده است، اما نیاز به درک دارد. اول، بیایید نگاه کنیم که در داخل عملکرد اتفاق می افتد.

تبریک تابع (نام) (
// LexicalEnvironment \u003d (نام: "نیکولای"، متن: undefined)
var text \u003d "سلام،" + نام؛
// LexicalEnvironment \u003d (نام: "نیکولای"، متن: "سلام، نیکولای")
هشدار (متن)؛
}

تبریک ("نیکولای")؛

آنچه در اینجا اتفاق می افتد و چه چیزی است lexicalEnvironment؟ بیایید آن را شکل دهیم

هنگامی که تابع نامیده می شود، یک شی را ایجاد می کند lexicalEnvironmentکه در آن همه متغیرها و توابع محلی ثبت می شوند، و همچنین اشاره به دامنه خارجی (در مورد این بعد). در مورد ما، ما یک متغیر محلی داریم نام.که بلافاصله یک مقدار (پس از آن ما عبور می کنیم) و این "نیکولای". با این حال، در یکی از مقالاتی که قبلا نوشتم، به شما یادآوری می کنم که تفسیر کننده همه چیز را در مورد همه متغیرها پیش از آن می داند. این در مورد این است که در ابتدای عملکرد در حال حاضر متغیر است متن، مترجم در مورد آن می داند، اما از آنجایی که ما هنوز به تخصیص این متغیر از نوع خاصی رسیدیم، برابر است undefined. حالا ما یک مقدار متغیر و شیء ما را اختصاص می دهیم lexicalEnvironment تغییرات اموال او متن این همان چیزی است که ما ثبت نام کردیم ("سلام، نیکولای" در مورد ما). پس از عملکرد، شیء کار کرده است lexicalEnvironment از بین رفتن. با تماس های بعدی، آن را دوباره ایجاد خواهد شد، و غیره

ما اکنون به مثال بعدی می رویم. به من بگویید چه چیزی در این مورد مشتق خواهد شد؟

var b \u003d 2؛
تابع x (a) (
هشدار (a + b)؛
}
x (1)؛

فکر؟ من فکر می کنم بیشتر پاسخ داد که شماره 3 نمایش داده خواهد شد، و این پاسخ درست است، با این حال شما می توانید به شما بگویم که چگونه مترجم در مورد متغیر آموخته است ب؟ پس از همه، آن را در عملکرد بدن نیست. اگر نه، بیایید درک کنیم.

در واقع در جاوا اسکریپت یک اموال پنهان به نام [] . هنگامی که تابع اعلام می شود، همیشه در جایی اعلام شده است. این ویژگی ممکن است در عملکرد دیگری باشد، ممکن است در یک شیء جهانی و غیره باشد در مورد ما، تابع در شیء جهانی اعلام شده است. پنجرهبنابراین، اموال x [] \u003d پنجره.

var b \u003d 2؛
تابع x (a) (// x. [] \u003d پنجره
// LexicalEnvironment \u003d (A: 1) -\u003e پنجره
هشدار (a + b)؛
}
x (1)؛

این فلش یک شی دارد lexicalEnvironment - این یک اشاره به دامنه خارجی است، و این لینک توسط اموال ایجاد شده است. [] . بنابراین در جسم lexicalEnvironment ما یک اشاره به یک شی خارجی خواهیم داشت. پنجره. هنگامی که مترجم به دنبال یک متغیر است، او برای اولین بار آن را در جسم جستجو می کند lexicalEnvironmentسپس، اگر او یک متغیر پیدا نکرد، پس از آن به لینک نگاه می کند، به دامنه خارجی می رود و برای آن جستجو می شود و به پایان می رسد. اگر او این متغیر را در هر نقطه پیدا نکرده باشد، خطایی خواهد بود. در مورد ما، متغیر آ. مترجم از جسم خارج خواهد شد lexicalEnvironment، و متغیر ب از جسم پنجره. البته، اگر ما یک متغیر محلی داشته باشیم ب با ارزش، آن را در جسم ثبت می شود lexicalEnvironment و پس از آن از آنجا گرفته خواهد شد، و نه از میدان خارجی دید.

مهم! به یاد داشته باشید که اموال [] این منطقه توسط جایی که تابع اعلام شد نصب شده است، و به این دلیل است که به همین دلیل کد زیر شماره 3 را نمایش می دهد، و نه 5، به عنوان برخی ممکن است فکر می کنم.

نوار B \u003d 2؛
تابع x (a) (
هشدار (a + b)؛
}

تابع y () (
var b \u003d 4؛
x (1)؛
}

این همه مقدمه ای بود که فقط درک نحوه این کار را انجام داد، و برای شما آسان تر بود که درک کنیم که چگونه بسته شدن کار می کرد. و اکنون ما به طور مستقیم به موضوع مقاله تبدیل می شویم.

همانطور که گفتم، جسم lexicalEnvironment هر بار هر بار پس از اجرای تابع، هر بار تخریب می شود و دوباره هنگام برقراری تماس دوباره ایجاد می شود. با این حال، اگر ما می خواهیم این داده ها را ذخیره کنیم چه؟ کسانی که. ما می خواهیم همه چیز را ثبت کنیم lexicalEnvironment در حال حاضر، حفظ شده است و برای چالش های زیر مورد استفاده قرار گرفت؟ این برای این است که بسته.

تبریک تابع (نام) (
// LexicalEnvironment \u003d (نام: "نیکولای")
تابع بازگشت () (// [] \u003d lexicalEnvironment
هشدار (نام)؛
};
}

var func \u003d تبریک ("نیکولای")؛
تبریک \u003d null؛
func ()؛

بیایید ببینیم چه کاری انجام دادیم ابتدا یک تابع ایجاد می کنیم تبریک.که در آن نام گذشت این تابع یک شی را ایجاد می کند lexicalEnvironmentجایی که اموال ایجاد می شود (متغیر محلی ما) نام. و او نام "نیکولای" را تعیین می کند. و در حال حاضر مهم است: ما یک تابع دیگر را از تابع، که در آن ما از طریق هشدار متغیر نام.. علاوه بر این ما یک متغیر را اختصاص می دهیم func ارزش بازگشت از عملکرد تبریک.و این مقدار تابع ما است که یک نام را نشان می دهد. حالا ما تبریک. ما اختصاص می دهیم خالی. ما فقط تابع ما را از بین می بریم تبریک.، با این حال، زمانی که ما تماس می گیریم funcسپس ارزش متغیر را مشاهده خواهیم کرد نام.("نیکولای") توابع تبریک.. چگونه می توان به شما بگوید؟ و بسیار ساده است. نکته این است که تابع بازگشتی ما نیز دارایی است. [] که به دامنه های خارجی دید اشاره دارد، این دامنه خارجی در مورد ما یک شی است lexicalEnvironment تابع ما تبریک.. بنابراین، با وجود این واقعیت که ما عملکرد ما را حذف می کنیم تبریک.، یک شی lexicalEnvironment حذف نشده و در حافظه باقی مانده است، و آن را در حافظه باقی خواهد ماند تا حداقل یک لینک باشد. ما این لینک را داریم - عملکرد بازگشتی ما که از متغیر استفاده می کند نام. از این تسهیلات lexicalEnvironment.

بنابراین، اجازه دهید اکنون تعریف کنیم بسته شدن چیست؟.

جریان - عملکرد با تمام متغیرهایی که برای آن در دسترس هستند.

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

تابع makecounter () (
var currrecount \u003d 0؛

تابع بازگشت () (
CurrentCount ++؛
بازگشت CurrentCount؛
};
}

var counter \u003d makecounter ()؛
پیشخوان ()؛
پیشخوان ()؛
هشدار (counter ())؛ // 3.

که در توابع جاوا اسکریپت می توان نه تنها یکی پس از دیگری، بلکه یکی را نیز در داخل دیگر توصیف کرد. هنگامی که شما یک تابع را در داخل دیگر قرار می دهید، جابجایی داخلی به یک تابع خارجی متناوب دسترسی دارد.

عملکرد خارجی (x) (var tmp \u003d 3؛ عملکرد داخلی (y) (هشدار (x + y + (+ ++ tmp))؛ // حذف 16) داخلی (10)؛) خارجی (2)؛

این کد همیشه به 16 می رسد، زیرا عملکرد داخلی X را می بیند، که یک متغیر در فانتزی خارجی است. که در این مورد تابع استدلال همچنین داخلی () می تواند TMP را از خارجی () مشاهده کند.

این بسته یا بسته شدن نامیده می شود. اگر دقیق تر باشد، بسته شدن عملکرد خارجی نامیده می شود و همه چیز درون آن محیط زیست یا محیط بسته شدن نامیده می شود.

گاهی اوقات گفته شده است که بسته شدن یک تابع است که عملکرد را باز می کند، به طور نادرست است، به منظور نام عملکرد بسته شدن که عملکرد داخلی به متغیر از خارج از محدوده آن اعمال می شود.

تابع foo (x) (var tmp \u003d 3؛ تابع بازگشت (Y) (هشدار (x + y + (+ ++ tmp))؛ // همچنین هشدار 16)) var bar \u003d foo (2)؛ // نوار در حال حاضر بسته شدن است. نوار (10)؛

عملکرد فوق نیز 16 نمایش داده خواهد شد، از آنجا که نوار حتی پس از آنکه Foo ادامه دارد، همچنان به X و TMP دسترسی پیدا می کند، حتی اگر متغیر نوار خود در داخل دامنه ای که آنها اعلام می شود، در دسترس قرار نگرفت.

در همان زمان، از آنجا که متغیر TMP هنوز در داخل بسته شدن نوار است، همچنان به افزایش هر بار تماس می دهد.

اینجا ساده ترین مثال جریان:

var a \u003d 10؛ تست تابع (console.log (a)؛ // نتیجه گیری 10 console.log (b)؛ // نتیجه گیری 6) var b \u003d 6؛ تست ()؛

هنگامی که شما یک تابع را در جاوا اسکریپت شروع می کنید، محیط زیست برای آن ایجاد می شود، یعنی یک لیست از تمام متغیرهای قابل مشاهده برای آن، نه تنها استدلال ها و متغیرها آن را در آن اعلام کرد، بلکه در خارج از این، در این مثال، "A" "و" ب ".

شما می توانید بیش از یک بسته را در یک محیط ایجاد کنید، آنها را به یک آرایه، شی یا پیوستن به یک متغیر جهانی بازگردانید. در این مورد، همه آنها کار خواهند کرد همان X یا مقدار TMP بدون ایجاد نسخه های شخصی.

از آنجا که در مثال X x عدد است، ارزش آن است کپی 🀄 در foo به عنوان استدلال آن X.

از سوی دیگر، جاوا اسکریپت همیشه از لینک هایی استفاده می کند که اشیاء منتقل می شوند. اگر شما Foo را با یک شی به عنوان یک استدلال نامید، بسته شدن بازگشت لینک را به شی اصلی بازگردانید!

تابع foo (x) (var tmp \u003d 3؛ عملکرد بازگشت (y) (هشدار (x + y + tmp)؛ x.memb \u003d x.memb؟ x.memb + 1: 1؛ هشدار (x.memb)؛) ) VAR AGE \u003d شماره (2)؛ var bar \u003d foo (سن)؛ // بار در حال حاضر بسته شدن به سن است. نوار (10)؛

همانطور که انتظار می رود، هر نوار تماس (10) X.MEMB را افزایش می دهد. آنچه شما ممکن است انتظار نداشته باشید، به طوری که X همچنان به همان شیء به عنوان سن اشاره دارد! پس از دو بار تماس، AGE.MEMB برابر با 2 خواهد بود! به هر حال، حافظه در اشیاء HTML رخ می دهد.

در برنامه نویسی، بسته شدن یا در نسخه انگلیسی زبان "بسته شدن" یک روش برای اجرای نام اتصال متنی در توابع کلاس اول است. به طور عملی، این یک ورودی است که عملکرد را همراه با رسانه ذخیره می کند. محیط زیست مقایسه هر عملکرد آزاد با یک مقدار یا مرجع به نام بسته بندی جاوا اسکریپت است. این اجازه می دهد تا دسترسی به متغیرهای ضبط شده را از طریق کپی مقادیر یا پیوندها، حتی زمانی که در خارج از منطقه ایجاد شود.

مفهوم بسته شدن

بسته شدن در دهه 1960 برای ارزیابی مکانیکی عبارات در محاسبات توسعه یافت و در سال 1970 به عنوان یکی از ویژگی های زبان برنامه نویسی PAL برای حمایت از توابع درجه اول با حوزه واژگانی استفاده شد. پیتر لاینن اصطلاح "بسته شدن" را در سال 1964 با بخش متوسط \u200b\u200bو کنترل که در دستگاه SECD مورد استفاده قرار گرفت، برای ارزیابی عبارات لامبدا مرتبط با یک محیط واژگانی که منجر به بستن آنها یا بسته شدن به جاوا اسکریپت شد، تعریف کرد.

چنین توضیحی در سال 1975 به عنوان یک نسخه LISP محدود LISP و گسترده بود. محیط واژنی انواع متغیرهای معتبر در برنامه است. این شامل یک الگوی داخلی داخلی و اشاره به یک محیط خارجی به نام متغیرهای غیر محلی است.

بسته شدن Lexic در جاوا اسکریپت ویژگی های محیط خارجی آن است. همانطور که در جاوا اسکریپت، تمام متغیرها یک پیوند به نوع دارند. JS فقط با استفاده از مرجع استفاده می شود - که مربوط به C ++ 11 است و طول عمر متغیرهای غیر محلی که توسط تابع گرفته شده توسط تابع گرفته می شود، در طول عمر عملکرد توزیع می شود.

مدارها در جاوا اسکریپت معمولا به زبان ها با مقادیر درجه اول ظاهر می شوند. چنین زبانهایی به شما این امکان را می دهد که توابع را به عنوان استدلال انتقال دهید. و همچنین از تماس های ویژگی باز می گردد و به نام های متغیر پیوست. این اتفاق می افتد مانند نوع ساده، مانند رشته ها و عدد صحیح.

در این مثال، بیان Lambda (Lambda (\u003e \u003d (کتاب فروشی کتاب فروشی) آستانه) در داخل عملکرد بهترین فروش کتاب ظاهر می شود. هنگامی که بیان لامبدا محاسبه می شود، مدار یک بسته را تشکیل می دهد که شامل کد برای بیان لامبدا و مرجع به متغیر آستانه است که یک متغیر آزاد در بیان لامبدا است. بسته شدن پس از آن توسط تابع فیلتر منتقل می شود که باعث می شود آن را بارها و بارها تعیین کنید تا مشخص شود کدام کتاب ها باید به لیست نتایج اضافه شوند و باید از بین برود.

از آنجا که در ارزش آستانه بسته شدن وجود دارد، دومی می تواند از آن هر بار که فیلتر آن را استفاده می کند استفاده کند. عملکرد فیلتر خود را کاملا می توان به طور کامل تعریف کرد فایل جداگانه. در اینجا یک مثال مشابه است، در JS بازنویسی شده است. این نشان می دهد که چگونه بسته های زیر کاپوت در جاوا اسکریپت کار می کنند.

کلمه کلیدی در اینجا به جای عملکرد فیلتر جهانی استفاده می شود، اما بقیه ساختار و اثر کد یکسان هستند. این تابع می تواند نزدیکتر شود و آن را بازگرداند، زیرا در این مورد، اجرای تابع را با متغیرهای F و DX ادامه می دهد پس از مشتق، حتی اگر اعدام دامنه آنها را ترک کند، و دیگر قابل مشاهده نیست.

در زبانها، بدون بسته شدن، طول عمر متغیر اتوماتیک محلی با اجرای فریم پشته همخوانی دارد، جایی که این متغیر اعلام شده است. به زبانهای با جاوا اسکریپت، بسته شدن و توابع IIFE، متغیرها باید تا زمانی که هر قفل موجود به آنها اشاره داشته باشد، باید ادامه یابد. این اغلب با استفاده از برخی از شکل جمع آوری زباله ها اجرا می شود.

مزیت بسته شدن این است که این دامنه، "زنجیره دید" یک زمینه خارجی یا "والدین" را حفظ می کند. چنین رفتارهایی را می توان به روش های مختلفی مورد استفاده قرار داد و تبدیل به یک ابزار مفید برای جلوگیری از انواع خطاهای جاوا اسکریپت شد. یکی از رایج ترین مسئله "حلقه ها" است.

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

  1. آنها می توانند برای تعیین ساختارهای کنترل استفاده شوند. به عنوان مثال، تمام ساختارهای مدیریت استاندارد SmallTalk، از جمله شاخه ها (اگر / پس از آن / دیگر) و چرخه ها (در حالی که برای آنها)، با استفاده از اشیاء که روش های آنها بسته می شود تعیین می شود. کاربران همچنین می توانند به راحتی از بسته شدن برای تعیین ساختار کنترل استفاده کنند. در زبان هایی که هدف را اجرا می کنند، می توانید رسانه های چند منظوره خود را ایجاد کنید، به شما این امکان را می دهد که به طور محرمانه ارتباط برقرار کنید و این محیط را تغییر دهید. بسته شدن برای پیاده سازی سیستم های شیء استفاده می شود.
  2. ایجاد هر دو روش متغیر خصوصی و عمومی با استفاده از قالب های ماژول. با توجه به این واقعیت که ویژگی های بازگشتی به ارث بردن منطقه عملکرد والدین، آنها برای همه متغیرها و استدلال در این زمینه در دسترس هستند.
  3. این در وضعیتی مفید است که این تابع از همان منبع برای هر تماس استفاده می کند، اما همچنین منابع خود را برای آن ایجاد می کند. این شرایط باعث ناکارآمد می شود که به طور انحصاری از بین می رود.

با توجه به MDN (شبکه توسعه دهنده موزیلا) "بسته شدن توابع با متغیرهای مستقل است که" به یاد داشته باشید "محیط زیست خلقت آن". و، به عنوان یک قاعده، زمانی که عملکرد کامل شده است، متغیرهای محلی آن دیگر وجود ندارد. درک کنید که چگونه بسته شدن جاوا اسکریپت کار می کند، شما می توانید مکانیزم های مختلف را در نظر بگیرید. اولین منطق رسمی است. به عنوان مثال، استفاده از تابع logName، که یک نام را به عنوان یک پارامتر می گیرد و آن را ثبت می کند. سپس من را برای چرخه برای رفتن از طریق لیست اسامی ایجاد می کنم، زمان بندی 1 را تنظیم می کنم و سپس تابع logname را در نام فعلی فراخوانی می کنم.

در زبان کلاس اول، شما می توانید به همان شیوه ای به عنوان انواع دیگر داده ها، مانند Int یا String دستکاری کنید. فقط این مکانیسم اجازه می دهد بسیاری از چیزهای باور نکردنی، به عنوان مثال، برای تعیین یک تابع متغیر به تماس بعدی و یا انتقال آن به عنوان یک پارامتر از یک تابع دیگر.

این اصل توسط بسیاری از سازه ها، و همچنین رویدادهای رویدادهای DOM استفاده می شود. اول، این رویداد "گوش دادن" است، سپس یک تابع فراخوانی را به نام هر بار که رویداد شروع می شود، اختصاص دهید.

تابع ناشناس یک تابع بدون نام است. برنامه نویسان تازه کار روزانه آنها را بدون درک بازی با اعداد ملاقات می کنند. به عنوان مثال، انجام عملیات اضافی، شما می توانید از طریق متغیرها، به عنوان مثال:

  • var x \u003d 3؛
  • y \u003d 5؛
  • var z \u003d x + y.

یا اگر شما قصد ندارید دوباره پردازش کنید: var z \u003d 3 + 5؛

این اتاق های ناشناس هستند. برای توابع ناشناس، شما می توانید آنها را اعلام کنید زمانی که آنها "در پرواز" استفاده می شود - بدون عبور متغیر. به عنوان مثال، عملکرد را از قبل انجام دهید:

(هشدار ("Ceci Est Une Fonchan Anonyme")؛

علاوه بر این، یک نحو جایگزین از اعلام یک تابع وجود دارد که تاکید می کند که هر دو توابع می توانند ناشناس باشند و به متغیرهای ساده مراجعه کنند، که یک راه مناسب برای نصب تابع فراخوانی است.

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

این در واقع دشوار است، اما جاوا اسکریپت راهی برای ردیابی دید از متغیرها و حتی دو طرف دارد. اختصاص یک متغیر جهانی در جاوا اسکریپت دارای مکانیزم مشابهی است که در جاوا - اشیاء پیچیده، آرایه ها، عناصر DOM و دیگران توسط مرجع منتقل می شوند، بنابراین در کد زیر:

var tab \u003d؛ var tab2 \u003d tab.

کجا، Tab و Tab2 دو پیوند به همان جدول هستند، از لحاظ فنی این شاخص ها توسط جمع کننده زباله کنترل می شوند. توابع نیز توسط مرجع منتقل می شوند. متغیر GlobalFn دیگر پنهان نیست. سفارش اجازه می دهد تا شما را به انجام آنچه که در مثال یک کار بسته بندی جاوا اسکریپت نشان داده شده است.

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

// Retourne 0 Inc ()؛

// Retourne 1 INC ()؛

// Retourne 2 INC ()؛

با بسته شدن آن به نظر می رسد:

عملکرد micinc () (var x \u003d 0؛ تابع بازگشت () (بازگشت x ++؛)) var inc \u003d makeinc ()؛

در آخرین ردیف در حال حاضر زمانی که متغیر وارز ایجاد شده است، برخی از متغیرهایی که در اطراف هستند، در این مورد X حمل می شود. این یک شیء نامرئی خاصی را در اطراف تابع حاوی این متغیر ایجاد می کند. این شیء یک تابع بسته شدن جاوا اسکریپت است. در عین حال، هر کپی از تابع بسته شدن خود را دارد:

var inc1 \u003d makinc ()؛

var inc2 \u003d makinc ()؛

همانطور که دیده می شود، بسته شدن در بسیاری موارد بسیار مفید است.

برای جلوگیری از درگیری های نام متغیر، فضای نام معمولا استفاده می شود. در جاوا اسکریپت، فضاهای فضایی اشیاء مانند هر چیز دیگری هستند.

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

در این تابع ناشناس از یک متغیر محلی، پاراگراف استفاده کنید. این یک راه عالی برای جلوگیری از درگیری های نام یا ناامیدی است، بلکه علیه ataks XSS. متغیرهای سفارشی محافظت می شوند، هیچ کس نمی تواند آنها را تغییر دهد تا بر رفتار اسکریپت تاثیر بگذارد.

یک گزینه وجود دارد: (تابع () (/ / / ...) ())؛

در عین حال توجه به جایگزینی براکت ها را جلب کنید. تفاوت بین این دو گزینه بسیار دشوار است توضیح دهید زیرا آنها با نحوه خواندن کد توسط یک آنالیز کننده واژگانی خوانده می شوند. در هر دو مورد، تابع به عنوان بیان در نظر گرفته می شود، اما این عبارت به طور همزمان تخمین زده نمی شود. فقط باید به یاد داشته باشید که او دو جفت براکت دور را می گیرد: یکی در اطراف عملکرد و یکی پشت آن.

برنامه نویسی جاوا اسکریپت در چرخه

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

در حال حاضر راه حل ساده ساده برای این مشکل وجود دارد، زیرا اجازه دهید کلمه کلیدی هر دو در فایرفاکس و در کروم پشتیبانی می شود. این است کلمه کلیدی به جای بلوک متغیر var. اجازه دهید به طور جادویی کار کند، زیرا یک متغیر جدید J اعلام شده است، ارزش آن که ارزش آن با بسته شدن در داخل چرخه ثابت شده است. با این حال، باید در ذهن داشته باشیم که پس از پایان تکراری چرخه، همچنان ادامه نمی یابد، زیرا آن را به صورت محلی وجود دارد.

حلقه و عملکرد

برای یک حلقه در جاوا اسکریپت ظاهر نمی شود، و همچنین برای یک چرخه در C یا جاوا. در واقع، به نظر می رسد مانند PHP. مهمترین دانش در مورد چرخه های JS این است که آنها یک منطقه را ایجاد نمی کنند. JS یک بلوک از کره ندارد، تنها عملکرد حجم. این ویژگی را می توان در بخش زیر در نظر گرفت:

تابع foo () (var bar \u003d 1؛

برای (var i \u003d 0؛ i< 42; i++) {var baz = i;} /* more code */}

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

کرکره ها و تجمع

بسته شدن چیزی بیش از توابع، درون توابع دیگر نیست و به برخی از زمینه های دیگر منتقل می شود. آنها بسته شدن نامیده می شوند، زیرا آنها از طریق متغیرهای محلی نزدیک می شوند، یعنی دسترسی به سایر زمینه های حوزه. به عنوان مثال، زمان، X به عنوان پارامتر Foo تعریف شده و var bar \u003d foo (2) () 84 را باز می گرداند.

تابع Foo بازگشت دسترسی به X دارد. این همه مهم است، زیرا به توسعه دهندگان کمک می کند تا توابع داخل چرخه را بسته به متغیرهای چرخه ایجاد کنند. این قطعه را در نظر بگیرید، که پردازنده را به عناصر مختلف اختصاص می دهد:

// عناصر آرایه ای از 3 عنصر عناصر Var varies \u003d ["foo"، "bar"، "baz"]؛

من.< l; i++) {var data = values[i];

عناصر [I] .onclick \u003d function () (هشدار (داده)؛

ارزش آنها از هشدار استفاده می کنند، زمانی که فشرده می شوند، برای همه، یعنی BAZ یکسان خواهد بود. در آن زمان، مدیر رویداد نامیده می شود، برای قبلا تکمیل شده است. JS یک منطقه بلوک ندارد، I.E. تمام دستگیره ها از لینک به یک متغیر داده استفاده می کنند. پس از حلقه، این مقدار ارزش خواهد بود. هر اعلام متغیر یک مکان را در حافظه ذخیره سازی ایجاد می کند. در آن، این داده ها دوباره و دوباره تغییر می کنند، موقعیت حافظه بدون تغییر باقی می ماند.

هر رویداد Handler به همان موقعیت در حافظه دسترسی دارد. تنها راه حل این است که وارد یک منطقه دیگر که "رفع" مقدار داده فعلی را رفع می کند. JS تنها دارای طیف وسیعی از توابع است. بنابراین، یک تابع دیگر وارد شده است. مثال:

تابع createeventhandler (x) (عملکرد بازگشت () (هشدار (x)؛

برای (var I \u003d 0، l \u003d lements.length؛

من.< l; i++) {var data = values[i];

عناصر [I] .onclick \u003d Createeventhandler (داده ها)؛

این کار می کند، زیرا مقدار داده ها در منطقه محلی ذخیره می شود، CreateeVenthandler و این تابع بر روی هر تکرار انجام می شود. این را می توان به طور خلاصه نوشته شده، با استفاده از توابع اجرایی بلافاصله:

برای (var I \u003d 0، l \u003d lements.length؛

من.< l; i++) {var data = values[i];

عناصر [I] .onclick \u003d (تابع (x) (تابع () (هشدار (x)؛

مثال عملی بسته شدن جاوا اسکریپت

اگر کاربر درست بالای کد در مرورگر بسته شود، ممکن است یک مشکل روبرو شود، زیرا می تواند هر گونه خطای نحو را ایجاد کند. اگر کد را به طور مستقیم در مرورگر اجرا کند، شانس بسیار زیاد نیست که فرایند کامپایل وبسایت را کامپایل کند. راه حل های ممکن:

کار تابع (نام) (

تابع بازگشت (موضوع) (

cONSOLE.LOG ($ (موضوع) در $ (نام))؛

کار ("جاوا اسکریپت") ("بسته شدن")؛

اول، تابع نامیده می شود و استدلال نام منتقل می شود. در حال حاضر این عملکرد واژگان نیز یک تابع را باز می کند که همچنین استدلال موضوعات را قبول می کند. این ویژگی خروجی را ثبت می کند و خروجی به متغیر دسترسی دارد.

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

یک مثال از یک تابع داخلی

بیشتر بخوانید در مورد بسته شدن جاوا اسکریپت را می توان در مثال دوم بیان کرد. در حال حاضر این محیط تحقق تخریب شده است، اما نام پارامتر هنوز وجود دارد. یک محیط کاربردی جدید داخلی ایجاد شده است، که یک تابع ناشناس است. این دسترسی به منطقه محیط زیست بیرونی است.

بنابراین، در یک متغیر از محیط خارجی، هنوز هم به گونه ای وجود دارد که یک تابع ناشناس دسترسی به نام متغیر متغیر در کنسول، به عنوان مثال، "بسته شدن در جاوا اسکریپت" چیست؟ عملکرد داخلی ناشناس //main.js

کارخانه تابع () (var products \u003d؛

i ++) (products.push (function (console.log (i)؛

) محصولات بازگشت؛

) var soap \u003d کارخانه ()؛

نتیجه این مثال نسبتا ناچیز و برابر 2 است.

هنگامی که صابون صابون () یک متغیر زمینه خارجی نامیده می شود، همیشه 2، زیرا در چرخه وضعیت در من نادرست است<2, поэтому при этом значение i равно 2, а во время вызова нужно напечатать значение в консоль так, она всегда пишет 2. То же самое для мыла - soap ().

ایجاد توابع "در پرواز"

شما می توانید یک کارخانه توابع ایجاد کنید - FunctionFactory که وظایف سفارشی را انجام می دهد. عملکرد حاصل از کارخانه توابع بسته شدن، محفظه ذخیره سازی ایجاد خواهد شد.

var functicactory \u003d function (num1) (بازگشت num1 * num2؛

بالا به شما اجازه می دهد تا یک شماره عملکرد را انتقال دهید. سپس ConfectFactory یک بسته شدن را باز می گرداند، به یاد آوردن مقدار num1. تابع حاصل مقدار اصلی Num1 برابر مقدار num2 را افزایش می دهد، که هنگام ارسال آن انتقال می یابد.

var mult5 \u003d functionfactory (5)؛

var mult10 \u003d functionfactory (10)؛

به سادگی به سادگی توابع چند و چند و چندانی را ایجاد می کند. در حال حاضر شما می توانید به هر یک از این توابع با عبور از یک شماره جدید به ضرب 5 یا 10 اشاره کنید. حالا شما می توانید نتیجه را ببینید.

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

در این مقاله، من سعی خواهم کرد که زمینه های دید و بسته شدن جاوا اسکریپت را توضیح دهم، که در آن بسیاری از مشکلات تجربه می کنند.

معرفی

تقریبا چند مقاله در شبکه وجود دارد که در حال تلاش برای توضیح مناطق دید و بسته شدن هستند، اما به طور کلی، من می گویم که اکثر آنها کاملا قابل فهم نیستند. علاوه بر این، در برخی مقالات فرض شده است که شما قبل از 15 زبان دیگر برنامه ریزی شده است، هرچند من فکر می کنم اکثر مردم نوشتن در جاوا اسکریپت تنها در HTML و CSS تجربه کرده اند و نه در C یا Java.

در نتیجه، هدف این مقاله این است که برای همه توضیح دهید - محدوده دید و بسته شدن، همانطور که آنها کار می کنند، و مهمتر از همه این که مزیت آنها است. قبل از خواندن این مقاله، شما باید مفاهیم اساسی در مورد متغیرها و توابع جاوا اسکریپت را بدانید.

منطقه دید

محدوده به معنی جایی است که متغیرها و توابع در دسترس هستند، و در آن زمینه آنها اعدام می شوند. یک متغیر یا عملکرد را می توان در یک منطقه جهانی یا محلی تعریف کرد. متغیرها دارای عملکرد به اصطلاح قابلیت دید عملکرد هستند، و توابع همان محدوده را به عنوان متغیرها دارند.

دامنه جهانی

هنگامی که چیزی جهانی است، به این معنی است که از هر کجا در کد شما موجود است. یک مثال را در نظر بگیرید:

var monkey \u003d "gorilla"؛ تابع Greatvisitor () (بازگشت هشدار ("سلام عزیزم خواننده وبلاگ!")؛)

اگر این کد در یک مرورگر وب انجام شود، سپس منطقه دید قابل مشاهده است، تا آن را برای همه چیز که در پنجره اجرا می شود در دسترس خواهد بود.

دامنه محلی

در مقایسه با منطقه دید جهانی، منطقه دید محلی، زمانی است که چیزی تعریف شده و تنها در بخشی از کد، مانند یک تابع موجود است. یک مثال را در نظر بگیرید:

تابع talkdirty () (var jay \u003d "اوه، شما کمی عاشق VB، شما"؛ بازگشت هشدار (گفتن)؛ هشدار (گفتن)؛ // یک خطا را پرتاب کنید

در این مثال، متغیر گفتاری تنها در داخل تابع TalkDirty در دسترس است، که در خارج از آن تعریف نشده است. نکته: اگر شما با گفتن بدون کلمه کلیدی Var شناسایی شده اید، به طور خودکار تبدیل به جهانی می شود.

علاوه بر این، اگر توابع توزیع شده داشته باشید، عملکرد داخلی به توابع که در آن تعبیه شده است، و همچنین متغیرها خواهد بود:

تابع capitalizename (بازگشت firstname.tuppercase ()؛) var capitalized \u003d capitalizename ()؛ بازگشت سرمایه؛) هشدار (Savename ("رابرت"))؛ // بازگشت "رابرت"

همانطور که قبلا دیدید، عملکرد داخلی Capitalizename نیازی به انتقال هر پارامتر ندارد، زیرا این دسترسی کامل به پارامتر اول را در عملکرد خارجی Savename دارد. برای وضوح بیشتر، مثال دیگری را در نظر بگیرید:

تابع خواهر و برادر () (var siblings \u003d ["John"، "Liza"، "پیتر"]؛ تابع siblingcount () (var siblingslength \u003d siblings.length؛ بازگشت SiblingsLength؛) تابع joinsiBlingNames () (بازگشت "من" + siblingcount () + "خواهر و برادر: nn" + siblings.join ("n")؛) بازگشت joinsiBlingNames ()؛) Alert (خواهر و برادر ())؛ // خروجی ها "من 3 خواهر و برادر دارم: جان لیزا پیتر"

همانطور که می بینید، هر دو توابع داخلی به آرایه های خواهر و برادر دسترسی دارند و هر تابع داخلی به یک عملکرد داخلی دیگر از سطح مشابه دسترسی دارد (در این مورد، JoinsIblingNames دسترسی به SiblingCount دارد). با این حال، متغیر SiblingsLength در داخل SiblingCount تنها در داخل این تابع در دسترس است، I.E. در این زمینه دید.

جریان

حالا که شما یک ایده واضح تر از مناطق دید را دارید، ما به آنها بسته می شویم. مدار عبارتند از عبارات، معمولا توابع است که می تواند با مجموعه ای از متغیرها در یک زمینه خاص کار کند. یا کلمات ساده تر، توابع داخلی که به متغیرهای محلی از توابع خارجی اشاره می کنند، بسته شدن را تشکیل می دهند. مثلا:

تابع اضافه کردن (x) (بازگشت x + y؛)؛) var add5 \u003d افزودن (5)؛ var no8 \u003d add5 (3)؛ هشدار (NO8)؛ // بازگشت 8

بی حرکت اینجا چه خبره؟ بیایید دریابیم:

1. هنگامی که ما تابع اضافه می کنیم، عملکرد را باز می گردانیم.

2. این تابع زمینه را بسته می کند و حفظ نحوه پارامتر X در این زمان (به عنوان مثال، در این مورد، مقدار 5)

3. هنگامی که نتیجه تابع اضافه شده به متغیر افزودنی اختصاص داده می شود، همیشه می داند که X هنگام ایجاد این متغیر چیست.

4. متغیر افزودنی به یک تابع اشاره دارد که همیشه ارزش 5 را به هر استدلالی منتقل می کند.

5. این بدان معنی است که وقتی ما Add5 را با مقدار 3 تماس می گیریم، شماره 5 و 3 را به دست می آورید و 8 را باز می گرداند.

در واقع، در دنیای جاوا اسکریپت، تابع Add5 به نظر می رسد:

تابع add5 (y) (بازگشت 5 + y؛)

مشکل بدنام چرخه
چند بار چرخه هایی را ایجاد کردید که در آن شما می خواستید ارزش من را به هیچ وجه تعیین کنید، به عنوان مثال، یک عنصر، و درک کنید که تنها آخرین ارزش من بازگشته است؟

اشتباهدرخواست

بیایید به این کد نادرست که 5 عنصر را ایجاد می کنیم نگاه کنیم ، مقدار I را به عنوان متن به هر عنصر اضافه می کند، انتظار می رود که انتظار می رود که هشدار را با ارزش I برای این مرجع، I.E. همان مقدار در متن عنصر است. سپس عناصر به سند اسناد اضافه می شوند:

<5; i++) { link = document.createElement("a"); link.innerHTML = "Link " + i; link.onclick = function () { alert(i); }; document.body.appendChild(link); } } window.onload = addLinks;

هر عنصر حاوی متن صحیح است، I.E. "لینک 0"، "لینک 1"، و غیره اما هر چه پیوند شما را کلیک کنید، آن را با شماره 5 نشان می دهد 5. موضوع چیست؟ دلیل این است که ارزش متغیر من 1 را با هر تکرار چرخه افزایش می دهد و به همین دلیل رویداد OnClick اجرا نمی شود، اما به سادگی به عنصر اعمال می شود ارزش افزایش می یابد.

بنابراین، چرخه ادامه می یابد تا زمانی که من برابر با 5، که آخرین مقدار قبل از خروج از عملکرد addLinks است، ادامه می یابد. علاوه بر این، هر زمانی که رویداد OnClick باعث می شود، آخرین مقدار من گرفته شده است.

درخواست تجدید نظر مناسب

آنچه شما باید انجام دهید این است که یک بسته شدن ایجاد کنید. به عنوان یک نتیجه، هنگامی که شما مقدار I را به یک رویداد رویداد OnClick اعمال می کنید ، من در آن زمان ارزش من را تعیین می کنم. به عنوان مثال، مثل این:

تابع addlinks () (برای (var i \u003d 0، لینک؛ من<5; i++) { link = document.createElement("a"); link.innerHTML = "Link " + i; link.onclick = function (num) { return function () { alert(num); }; }(i); document.body.appendChild(link); } } window.onload = addLinks;

با استفاده از این کد، اگر شما بر روی عنصر اول کلیک کنید، هشدار به "0"، در دوم - "1" و غیره راه حل این است که عملکرد داخلی اعمال شده به رویداد OnClick یک بسته شدن را ایجاد می کند که در آن پارامتر شماره تجدید نظر، I.E. به ارزش من در آن زمان.

این ویژگی "به یاد" مقدار مورد نظر، و پس از آن می تواند رقم مربوطه را هنگامی که رویداد OnClick شروع می شود، بازگرداند.

توابع اجرای امن

توابع ایمن اجرای چنین توابع هستند که بلافاصله اجرا می کنند و بسته شدن خود را ایجاد می کنند. یک مثال را در نظر بگیرید:

(عملکرد () (var dog \u003d "چوپان آلمانی"؛ هشدار (سگ)؛)) ()؛ هشدار (سگ)؛ // بازپرداخت نامشخص

بنابراین، متغیر سگ تنها در این زمینه در دسترس است. فکر می کنم، سگ متغیر پنهان ... اما دوستان من، چیزهای جالب ترین با این شروع می شود! این مشکل ما را با یک چرخه حل کرد و همچنین پایه ای برای الگوی ماژول یاهو جاوا اسکریپت است.

الگوی ماژول یاهو جاوا اسکریپت

ماهیت این الگو این است که از یک تابع ایمن اجرایی برای ایجاد یک بسته استفاده می کند، بنابراین امکان استفاده از خواص و روش های خصوصی و عمومی را فراهم می کند. مثال ساده:

var person \u003d function () (/ / نام خصوصی خصوصی \u003d "رابرت"؛ بازگشت (getname: function () (نام بازگشت)، setname: function (newname) (new \u003d newname؛))؛) ()؛ هشدار (person.name)؛ // هشدار نامشخص (person.getname ())؛ // "رابرت" Person.Setname ("رابرت نین")؛ هشدار (person.getname ())؛ // "رابرت نین"

مزیت این رویکرد این است که شما می توانید خودتان را تعریف کنید، که در شیء شما باز می شود (و می تواند تغییر کند)، و آن بسته، که هیچ کس نمی تواند تماس بگیرد یا تغییر کند. متغیر نام در خارج از زمینه عملکرد پنهان است، اما برای عملکرد GetName و Setname قابل دسترسی است، زیرا آنها بسته شدن را ایجاد می کنند که در آن یک پیوند به متغیر نام وجود دارد.

نتیجه

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

کدگذاری خوب!

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

همانطور که می دانید، در جاوا اسکریپت زمینه دید از متغیرهای محلی (واژه var اعلام شده) این بدن از کارکردی است که آنها تعریف می شوند.

اگر شما یک تابع را در داخل یک تابع دیگر اعلام کنید، اولین دسترسی به متغیرها و استدلال های دوم را می دهد:

کد: عملکرد OUTERFN (MYARG) (
var myvar؛
تابع innerfn () (
// دسترسی به میوار و میراندار دارد
}
}

در عین حال، چنین متغیرها همچنان ادامه دارند و حتی پس از عملکردی که در آن تعریف شده اند، عملکرد داخلی را در دسترس قرار می دهند.

یک مثال را در نظر بگیرید - یک تابع که تعداد مقادیر خاص را باز می کند:

کد: عملکرد Createcounter () (
var numberofcalls \u003d 0؛
تابع بازگشت () (
بازگشت ++ numberofcalls؛
}
}
var fn \u003d createcounter ()؛
fn ()؛ // یکی
fn ()؛ // 2
fn ()؛ // 3.

در این مثال، تابع بازگشت توسط Createecounter با استفاده از متغیر NumberOfCalls، که موجب صرفه جویی در ارزش مورد نظر بین تماس های آن می شود (به جای بلافاصله توقف وجود خود را با بازگشت Createcounter).

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

استفاده از بسته شدن

یک مثال کوچک را ساده می کند - حذف نیاز به جداگانه تماس با عملکرد Createecounter، آن را آن را تجزیه و تحلیل و آن را بلافاصله پس از آگهی خود را.

کد: var fn \u003d (تابع () (
var numberofcalls \u003d 0؛
تابع بازگشت () (
بازگشت ++ numberofcalls؛
}
})();

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

دیگر استفاده خوب از بسته شدن - ایجاد توابع، به نوبه خود، همچنین ایجاد توابع - آنچه برخی از آنها به نام T.N.N. متاپوگرام
مثلا:

کد: var CreateEhelloFunction \u003d تابع (نام) (
تابع بازگشت () (
هشدار ("سلام،" + نام)؛
}
}
var sayhellohabrahab \u003d createhellofunction ("حبراباب")؛
sayhellohabrahabr ()؛ // هشدار "Hello، Habrahabr"

با تشکر از بسته شدن، عملکرد بازگشتی "به یاد می آورد" پارامترهای منتقل شده به توابع ایجاد که ما برای این نوع چیزها نیاز داریم.

یک وضعیت مشابه زمانی رخ می دهد که ما یک تابع داخلی را بازگردانیم و هر رویدادی را بچرخانیم - از آنجایی که این رویداد پس از انجام این کار صورت می گیرد، بسته شدن دوباره کمک می کند تا داده های ارسال شده را هنگامی که پردازشگر داده ایجاد می شود، از دست ندهد.

یک مثال کمی پیچیده تر را در نظر بگیرید - یک روش که عملکرد را به یک زمینه خاص متصل می کند (به عنوان مثال، جسم که این کلمه در آن نشان داده می شود).

کد: تابع.Prototype.Bind \u003d عملکرد (زمینه) (
var fn \u003d این؛
تابع بازگشت () (
بازگشت fn.apply (زمینه، استدلال)؛
};
}
var hellopage \u003d (
نام: "حلابرابر"،
init: function () (
هشدار ("سلام،" + this.name)؛
}
}
//window.onload \u003d hellopage.init؛ // Alertnul تعریف نشده است، زیرا این نشانگر پنجره است
window.onload \u003d hellopage.init.bind (hellopage)؛ // حالا همه چیز کار می کند

در این مثال، با کمک یک بسته شدن، یک تابع، باعث اتصال "OHM، عملکرد اولیه و زمینه اختصاص داده شده به آن را به یاد می آورد.

بعد، اساسا استفاده متفاوت از بسته شدن - حفاظت از داده ها (کپسوله سازی). طراحی زیر را در نظر بگیرید:

کد: (تابع () (

})();

بدیهی است، در داخل بسته شدن ما به تمام داده های خارجی دسترسی داریم، اما دارای خودش است. با توجه به این، ما می توانیم بخشی از کد مانند یک طراحی را احاطه کنیم تا متغیرهای محلی را از دسترسی خارج کنیم. (یک مثال از استفاده از آن را می توان در کد منبع کتابخانه جی کوئری مشاهده کرد، که بسته شدن تمام کد آن را احاطه کرده است تا متغیرها را فقط به آن منتقل کند).

با این حال، یکی از موارد مرتبط با چنین تله ای وجود دارد - معنای کلمه این در داخل بسته شدن از دست رفته است. این به شرح زیر است:

کد: (تابع () (
// بالاترین این ادامه خواهد یافت
)) تماس بگیرید (این)؛

دریافت یک پذیرش دیگر از همان سری. این به طور گسترده توسط توسعه دهندگان خود را از چارچوب یاهو UI محبوب شده است، به نام او "الگوی ماژول" و نوشتن یک مقاله کامل در آن در یک وبلاگ رسمی.
اجازه دهید ما یک شی (Singleton) حاوی هر روش و خواص داشته باشیم:

کد: var mymodule \u003d (
نام: "حلابرابر"،
saypreved: تابع (نام) (
هشدار ("Preved" + name.touppercase ())
},
این .saypreved (این نام)؛
}
}
mymodule.sayprevedtohabrahabrabrahabrahabr

با کمک بسته شدن، ما می توانیم روش ها و خواص را که در خارج از جسم استفاده نمی شود، ایجاد کنیم (به عنوان مثال در دسترس تنها به او):

کد: var mymodule \u003d (تابع () (
var name \u003d "habrahab"؛
تابع saypreved () (
هشدار ("Preved" + name.touppercase ())؛
}
برگشت (
sayprevedtohabrabrabr: تابع () (
SAYPREVED (نام)؛
}
}
})();
mymodule.s// هشدارها "Habrahab" را پیش برد "

سرانجام، من می خواهم یک اشتباه رایج را توصیف کنم که بسیاری از آنها در مورد جهل در مورد چگونگی بستن کار می کنند.

اجازه دهید یک آرایه از لینک ها داشته باشیم، و وظیفه ما این است که آن را به طوری که هنگام کلیک بر روی هر Allert، شماره توالی آن نمایش داده می شود.
اولین تصمیم که به ذهن می آید به نظر می رسد این است:

کد: برای (var i \u003d 0؛ i< links.length; i++) {
هشدار (I)؛
}
}

در واقع، به نظر می رسد که هنگامی که شما بر روی هر لینک کلیک کنید، همان شماره نمایش داده می شود - مقدار لینک ها. چرا این اتفاق می افتد؟ در ارتباط با بسته شدن، متغیر کمکی اعلام شده من همچنان وجود دارد، با و در حال حاضر زمانی که ما بر روی لینک کلیک کنید. از آن زمان تا آن زمان چرخه قبلا گذشت، من برابر با تعداد لینک ها باقی می ماند - این مقدار ما در هنگام کلیک روی قابل مشاهده است.

این مشکل به شرح زیر است:

کد: برای (var i \u003d 0؛ i< links.length; i++) {
(عملکرد (i) (
لینک ها [i] .onclick \u003d function () (
هشدار (I)؛
}
)) (من)؛
}

در اینجا، با کمک یک بسته دیگر، ما "سایه" متغیر I، ایجاد آن یک کپی در منطقه محلی خود را در هر مرحله چرخه. با تشکر از این، همه چیز در حال حاضر به عنوان درک شده است.

این همه است البته این مقاله ادعا نمی کند که جامع باشد، اما من امیدوارم، هنوز هم کمک می کند تا آن را بفهمید.

zy
برای صرفه جویی در میان تماس ها آسان تر برای استفاده از func_name.attr نوع:

کد: عملکرد COUNTIT (RESET) (
اگر (تنظیم مجدد ||! countit.cnt) countit.cnt \u003d 0؛
بازگشت countit.cnt ++؛