از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
عبارات توابع فراخوانی فوری جاوا اسکریپت تعریف و فراخوانی توابع، شیوه های کلیدی برای تسلط بر جاوا اسکریپت و بیشتر زبان های برنامه نویسی دیگر هستند. معمولاً یک تابع قبل از فراخوانی در کد شما تعریف می شود. عبارات تابع فوری فراخوانی شده (IIFE) که “iffy” تلفظ می شود، یک الگوی رایج جاوا اسکریپت است که یک تابع را بلافاصله پس از تعریف آن اجرا می کند. توسعه دهندگان در درجه اول …
سرفصلهای مطلب
معرفی
تعریف و فراخوانی توابع، شیوه های کلیدی برای تسلط بر جاوا اسکریپت و اکثر زبان های برنامه نویسی دیگر هستند. معمولاً یک تابع قبل از فراخوانی در کد شما تعریف می شود.
عبارات تابع فوری فراخوانی شده (IIFE) که “iffy” تلفظ می شود، یک الگوی رایج جاوا اسکریپت است که یک تابع را بلافاصله پس از تعریف آن اجرا می کند. توسعه دهندگان در درجه اول از این الگو استفاده می کنند تا اطمینان حاصل کنند که متغیرها فقط در محدوده تابع تعریف شده قابل دسترسی هستند.
در این مقاله ابتدا با عبارات تابع آشنا می شوید. پس از آن، ما عمیق تر به IIFE ها خواهیم پرداخت – چگونه آنها را بنویسیم و چه زمانی از آنها استفاده کنیم. در نهایت، ما در مورد چگونگی let
کلیدواژه معرفی شده در ECMAScript 6 جایگزین تمیزتری برای برخی موارد استفاده IIFE ارائه می دهد.
عبارات تابع چیست؟
در جاوا اسکریپت، می توانید یک تابع را به 2 روش مختلف تعریف کنید:
- یک اعلامیه
- یک بیان
اعلامیه های عملکرد با function
کلمه کلیدی، به دنبال آن نام تابع و هر آرگومان ممکن است. به عنوان مثال، می توانیم a ایجاد کنیم logName
عملکرد با استفاده از یک اعلان مانند زیر:
function logName(userName) {
console.log(`${userName}, you are awesome`);
};
logName("Jane");
از تعریف تابع، هر مقدار داده شده را در آن ثبت می کنیم message
پارامتر به console. سپس تابع را با “Jane, you awesome!” فراخوانی کردیم که این کار را انجام داد print آن متن به console.
هنگام تعریف یک تابع با استفاده از اعلان تابع، تابع است برافراشته شد. هنگامی که جاوا اسکریپت در حال اجرای کد است، یک تابع یا متغیر افزایش یافته در بالای محدوده عملکردی آنها قرار می گیرد.
توجه داشته باشید: Functional Scope به جایی اشاره دارد که یک تابع تعریف شده است. به عنوان مثال، اگر یک تابع
foo()
حاوی یک تابعbar()
در داخل آن، می گوییم که محدوده عملکردیbar()
استfoo()
. اگرfoo()
پس در یک تابع تعریف نشده بودfoo()
به گستره جهانی تعلق دارد. توابع جاوا اسکریپت در محدوده جهانی برای همه کدهایی که با آن اجرا می شود قابل دسترسی هستند.
در عمل، این رفتار به شما اجازه می دهد تا قبل از تعریف یک تابع از آن استفاده کنید. به عنوان مثال، کد قبلی را می توان به این شکل بازنویسی کرد و به همین ترتیب عمل می کند:
logName();
function logName(name) {
console.log(`${name}, you are awesome!`);
};
عبارات تابع تعاریف توابعی هستند که به یک متغیر اختصاص داده می شوند. بنابراین، ما logName()
اعلان تابع می تواند به یک عبارت تابع تبدیل شود اگر آن را به صورت زیر ایجاد کنیم:
const logUserName = function logName(name) {
console.log(`${name}, you are awesome!`);
};
logUserName("Jane");
در این مثال، برای فراخوانی تابع باید از نام متغیر ارائه شده استفاده کنیم – logUserName
. این رفتار عملکرد را تغییر نمی دهد، همچنان “You are awesome” را وارد می کند console.
برخلاف اعلان تابع، عبارات تابع هستند نه برافراشته شد. این توابع تنها زمانی در دسترس هستند که مفسر جاوا اسکریپت آن خط کد را پردازش کند.
مثلاً اگر سعی کردیم تماس بگیریم logUserName()
قبل از ایجاد آن به عنوان یک عبارت تابع:
logUserName("Jane");
const logUserName = function logName(name) {
console.log(`${name}, you are awesome!`);
};
خطای زیر را دریافت می کنیم:
Uncaught ReferenceError: Cannot access 'logUserName' before initialization
تفاوت دیگر بین عبارات تابع و اعلان تابع این است که عبارات تابع می توانند توابع را بدون نام تعریف کنند.
توابع بدون نام نامیده می شوند توابع ناشناس. مثلا، logUserName()
همچنین می تواند با یک تابع ناشناس مانند این تعریف شود:
const logUserName = function (name) {
console.log(`${name}, you are awesome!`);
};
توابع پیکان
توابع پیکان، قند نحوی را برای عبارات تابع ارائه می کنند. اجرای مجدد ما logUserName
تابع با استفاده از یک تابع فلش به شکل زیر است:
const logUserName = (name) => {
console.log(`${name}, you are awesome!`);
}
برای کسب اطلاعات بیشتر در مورد این نحو و روش تأثیر آن بر دامنه عملکرد، توابع پیکان را در جاوا اسکریپت بخوانید.
اکنون که می دانیم چگونه عبارات تابع مختلف را ایجاد کنیم، بیایید روش فراخوانی فوری آنها را بیاموزیم.
عبارات تابع بلافاصله فراخوانی شده چیست؟
IIFE ها توابعی هستند که اجرا می شوند سریعا بعد از در حال تعریف شدن
ما میتوانیم هر عبارت تابعی را با قرار دادن آن در پرانتز و اضافه کردن یک جفت پرانتز زیر به یک IIFE تبدیل کنیم:
(function() {
// Code that runs in your function
})()
همچنین، میتوانید از نحو فلش برای ایجاد یک IIFE به صورت زیر استفاده کنید:
(() => {
// Code that runs in your function
})()
پرانتزهای اطراف تعریف تابع به جاوا اسکریپت اجازه می دهد بداند که این کار را خواهد کرد process یک عبارت تابع آخرین جفت پرانتز تابع را فراخوانی می کند.
تغییرات نحوی
اگر از یک عملگر unary استفاده میکنید، میتوانید IIFE را بدون اولین مجموعه پرانتز ایجاد کنید – کاراکترهای خاصی که به جاوا اسکریپت میگویند عبارت زیر را ارزیابی کند.
ما می توانیم عبارات تابع را با عملگرهای یوناری مانند این ایجاد کنیم:
+function () {
// Code that runs in your function
}();
-function () {
// Code that runs in your function
}();
!function () {
// Code that runs in your function
}();
~function () {
// Code that runs in your function
}();
void function () {
// Code that runs in your function
}();
توجه به این نکته مهم است که این اپراتورها می توانند بر هر داده ای که توسط عملکرد شما برگردانده می شود تأثیر بگذارند. به عنوان مثال، کد زیر به نظر می رسد که باید بازگردد 10
، اما در واقع برمی گردد -10
:
$ node
> -function () {return 10;}();
-10
>
از آنجایی که این نحو یکنواخت کمتر رایج است و می تواند برای توسعه دهندگان گیج کننده باشد، به طور کلی توصیه نمی شود.
IIFE ها همچنین می توانند آرگومان های تابعی را دریافت کنند. ما می توانیم متغیرها را مانند شکل زیر به محدوده منتقل کنیم:
(function(arg1, arg2) {
// Code that runs in your function
})("hello", "world");
اکنون که روش ایجاد IIFE را دیدیم، بیایید به موقعیتهای رایج استفاده از آنها نگاه کنیم.
چه زمانی از IIFE استفاده کنیم؟
رایج ترین موارد استفاده برای IIFE ها عبارتند از:
- نام مستعار متغیرهای سراسری
- ایجاد متغیرها و توابع خصوصی
- توابع ناهمزمان در حلقه ها
نام مستعار متغیرهای جهانی
اگر 2 کتابخانه دارید که export یک شی با همین نام، می توانید از IIFE استفاده کنید تا مطمئن شوید که در کد شما تداخل ندارند. به عنوان مثال جی کوئری و پول نقد هر دو کتابخانه جاوا اسکریپت export $
به عنوان هدف اصلی آنها
می توانید کد خود را در یک IIFE قرار دهید که یکی از متغیرهای سراسری را به عنوان آرگومان ارسال می کند. بیایید بگوییم، ما می خواهیم از آن اطمینان حاصل کنیم $
اشاره به jQuery
شی، و نه cash
جایگزین. می توانید اطمینان حاصل کنید jQuery
با IIFE زیر استفاده می شود:
(function($) {
// Code that runs in your function
})(jQuery);
ایجاد متغیرها و توابع خصوصی
ما می توانیم از IIFEها برای ایجاد متغیرها و توابع خصوصی در محدوده جهانی یا هر محدوده تابع دیگری استفاده کنیم.
توابع و متغیرهای اضافه شده به دامنه جهانی برای همه اسکریپت هایی که بارگذاری می شوند در دسترس هستند روی آ page. فرض کنید ما یک عملکرد داشتیم generateMagicNumber()
، که یک عدد تصادفی بین 900 تا 1000 را شامل می شود و یک متغیر favoriteNumber
در فایل جاوا اسکریپت ما
می توانیم آنها را به این صورت بنویسیم:
function generateMagicNumber() {
return Math.floor(Math.random() * 100) + 900;
}
console.log("This is your magic number: " + generateMagicNumber());
var favoriteNumber = 5;
console.log("Twice your favorite number is " + favoriteNumber * 2);
اگر سایر فایل های جاوا اسکریپت را در مرورگر خود بارگذاری کنیم، آنها نیز به آنها دسترسی پیدا می کنند generateMagicNumber()
و favoriteNumber
. برای جلوگیری از استفاده یا ویرایش آنها، کد خود را در یک IIFE قرار می دهیم:
(function () {
function generateMagicNumber() {
return Math.floor(Math.random() * 100) + 900;
}
console.log("This is your magic number: " + generateMagicNumber());
var favoriteNumber = 5;
console.log("Twice your favorite number is " + favoriteNumber * 2);
})();
به همین صورت اجرا می شود، اما اکنون generateMagicNumber()
و favoriteNumber
فقط در اسکریپت ما قابل دسترسی هستند.
توابع ناهمزمان در حلقه ها
رفتار جاوا اسکریپت وقتی کال بک ها در حلقه ها اجرا می شوند، بسیاری را شگفت زده می کند. به عنوان مثال، بیایید از 1 تا 5 در جاوا اسکریپت بشماریم، و هر بار که یک پیام را ثبت می کنیم، 1 ثانیه فاصله بین آن قرار می دهیم. یک پیاده سازی ساده لوحانه خواهد بود:
for (var i = 1; i <= 5; i++) {
setTimeout(function () {
console.log('I reached step ' + i);
}, 1000 * i);
}
اگر این کد را اجرا کنید، خروجی زیر را دریافت خواهید کرد:
$ node naiveCallbackInLoop.js
I reached step 6
I reached step 6
I reached step 6
I reached step 6
I reached step 6
در حالی که خروجی 1 ثانیه پس از دیگری چاپ می شود، هر خط چاپ می کند که به مرحله 6 رسیده است. چرا؟
هنگامی که جاوا اسکریپت با کد ناهمزمان مواجه می شود، اجرای فراخوانی را تا تکمیل کار ناهمزمان به تعویق می اندازد. اینطوری غیر مسدود می ماند. در این مثال، console.log()
بیانیه فقط پس از سپری شدن مهلت زمانی اجرا می شود.
جاوا اسکریپت نیز یک بسته برای پاسخ به تماس ما بسته ها ترکیبی از یک تابع و محدوده آن هستند زمانی که ایجاد شد. با بسته شدن، تماس ما می تواند به متغیر دسترسی داشته باشد i
حتی اگر for
حلقه قبلاً اجرا شده است.
با این حال، تماس ما فقط به مقدار دسترسی دارد i
در زمان اجرای آن. به عنوان کد در setTimeout()
تابع همه به تعویق افتاد، for
حلقه با تمام شد i
برابر 6 بودن. به همین دلیل است که همه آنها وارد مرحله 6 شده اند.
این مشکل را می توان با یک IIFE حل کرد:
for (var i = 1; i <= 5; i++) {
(function (step) {
setTimeout(function() {
console.log('I reached step ' + step);
}, 1000 * i);
})(i);
}
با استفاده از یک IIFE، ما یک محدوده جدید برای عملکرد برگشت تماس خود ایجاد می کنیم. IIFE ما یک پارامتر می گیرد step
. هر بار که IIFE ما فراخوانی می شود، مقدار فعلی را به آن می دهیم i
به عنوان استدلال آن حال، زمانی که callback آماده اجرا شد، بسته شدن آن مقدار صحیح را خواهد داشت step
.
اگر این قطعه کد را اجرا کنیم، خروجی زیر را خواهیم دید:
$ node iifeCallbackInLoop.js
I reached step 1
I reached step 2
I reached step 3
I reached step 4
I reached step 5
در حالی که IIFEs مشکل ما را با حداقل تغییرات کد حل میکند، بیایید نگاهی بیندازیم که چگونه ویژگیهای ES6 میتوانند اجرای کدهای ناهمزمان را در حلقهها آسانتر کنند.
Block Scoping با let
و const
ES6 را اضافه کرد let
و const
کلمات کلیدی برای ایجاد متغیر در جاوا اسکریپت. متغیرهای اعلام شده با let
یا const
هستند محدوده بلوک. این بدان معنی است که آنها فقط در بلوک محصور خود قابل دسترسی هستند – منطقه ای که توسط بریس های فرفری محصور شده است { }
.
بیایید از 1 تا 5 در فواصل 1 ثانیه با استفاده از let
کلمه کلیدی به جای var
:
for (let i = 1; i <= 5; i++) {
setTimeout(function () {
console.log('I reached step ' + i);
}, 1000 * i);
}
با اجرای این کد خروجی زیر را دریافت خواهیم کرد:
$ node es6CallbackInLoop.js
I reached step 1
I reached step 2
I reached step 3
I reached step 4
I reached step 5
حالا که متغیر i
دارای محدوده بلوکی است، بسته های تابع برگشت به تماس ما مقدار مناسب را دریافت می کنند i
زمانی که آنها در نهایت اجرا می کنند. این مختصرتر از اجرای IIFE ما است.
استفاده کردن let
روش ترجیحی برای اجرای توابع ناهمزمان در یک حلقه است،
نتیجه
عبارت Invoked Function (IIFE) تابعی است که بلافاصله پس از تعریف اجرا می شود. این الگو برای نام مستعار متغیرهای سراسری، خصوصی کردن متغیرها و توابع و اطمینان از اجرای صحیح کدهای ناهمزمان در حلقه ها استفاده شده است.
با وجود محبوبیت، دیدیم که چگونه تغییرات در ES6 میتواند نیاز به استفاده از IIFE در جاوا اسکریپت مدرن را از بین ببرد. با این حال، تسلط بر این الگو همچنین به ما درک عمیق تری از محدوده و بسته شدن می دهد، و به ویژه در حفظ کد جاوا اسکریپت قدیمی مفید خواهد بود.
(برچسبها برای ترجمه)# جاوا اسکریپت
منتشر شده در 1403-01-23 00:54:03