در این مقاله، ما درباره متدهای apply، call و bind از زنجیره prototype (نمونه اولیه) تابع صحبت خواهیم کرد. این متدها، برخی از مهمترین و مورد استفادهترین مفاهیم در JavaScript بوده و خیلی به کلیدواژه this وابسته هستند.
پس برای این که اطلاعات موجود در این مقاله را در دست بگیرید، اول باید دانشی در زمینه JavaScript داشته باشید که در این جهت میتوانید نگاهی به دوره مربوطه بر روی راکت داشته باشید، و دوم هم باید با مفهوم کلیدواژه this و نحوه استفاده از آن آشنا شوید. اگر از پیش با آن آشنا هستید، حال میتوانید ادامه دهید؛ در غیر این صورت به مقاله «راهنمایی برای this در JavaScript» بروید و پس از مطالعه، به اینجا باز گردید.
برای یادگیری apply | call | bind، ما باید با فرض این که شما با this آشنا هستید، درباره توابع در JavaScript هم برخی چیزها را بدانیم.
توابع
سازنده تابع (Function constructor) یک آبجکت تابع جدید میسازد. فراخوانی مستقیم constructor، میتواند توابع را به طور دینامیک بسازد، و میتواند در محدوده global اجرا شود. با توجه به این که توابع در JavaScript، در واقع آبجکت هستند، فراخوانی آنها توسط متدهای apply، call و bind کنترل میشود. برای بررسی این که آیا یک تابع، یک آبجکت Function است یا نه، ما میتوانیم از کد موجود در قطعه کد زیر استفاده کنیم، که مقدار true را بر میگرداند.
آبجکت global با نام Function، هیچ متد یا ویژگیای از خود ندارد. گرچه، از آنجایی که خودش هم یک تابع است، هیچ متد یا ویژگیای را از طریق زنجیره prototype از Function.prototype به ارث نمیبرد.
متدهای زیر، متدهای موجود در زنجیره prototype تابع هستند:
- Function.prototype.apply()
- Function.prototype.bind()
- Function.prototype.call()
- Function.prototype.isGenerator()
- Function.prototype.toSource()
- Object.prototype.toSource()
- Function.prototype.toString()
- Object.prototype.toString
ما نگران سه مورد اول هستیم؛ پس بیایید شروع کنیم.
Apply
متد apply یک متد مهم از prototype تابع بوده، و برای فراخوانی توابع دیگر با یک مقدار کلیدواژه this و چند آرگومان فراهم شده در قالب آرایه یا هر آبجکتی به مانند یک آرایه استفاده میشود. آبجکتهای شبیه به آرایه، عبارتند از NodeList یا آبجکت آرگومانها داخل یک تابع. این یعنی ما میتوانیم هر آبجکتی را فراخوانی کنیم و به صراحت مشخص کنیم که this در تابع فراخوان، باید به چه چیزی اشاره داشته باشد.
سینتکس
مقدار برگشتی
این تابع نتیجه تابعی که توسط this فراخوانی شده است را بر میگرداند.
توصیف
متد apply برای این استفاده میشود که به یک تابع / آبجکت که به یک آبجکت مانند x تعلق دارد، اجازه دهیم فراخوانی شده، و یا به یک آبجکت دیگر مثلا y اختصاص داده شود.
مثالها
۱:
همانطور که در این قطعه کد دیده میشود، ما میبینیم که وقتی یک آرایه را داخل یک آرایه دیگر هول میدهیم، با کل آرایه به عنوان یک عنصر رفتار میشود و به متغیر آرایه هول داده میشود. اما اگر بخواهیم عناصر به جای یک آرایه، به صورت جداگانه هول داده شوند چه؟ مطمئنا چندین راه برای انجام این کار وجود دارد، اما با توجه به این که ما در حال یادگیری apply هستیم، بیایید از آن استفاده کنیم:
در مثال بالا، ما میتوانیم استفاده از apply در الحاق دو آرایه داده شده را ببینیم. آرایه آرگومانها، آرایه عناصر است و آرگومان this به متغیر آرایه اشاره دارد. عناصر موجود در آرایه عناصر، به Object(array) هول داده میشوند که this هم به آن اشاره دارد. همینطور که عناصر جداگانه آرایه دوم، به آرایهای هول داده میشوند که this به آن اشاره دارد، ما نتیجه مد نظر را به دست میآوریم.
۲:
تابع max در JS برای یافتن عنصر دارای بالاترین مقدار از مجموعهای از عناصر داده شده استفاده میشود. اما همانطور که میتوانید از قطعه کد پیشین ببینید، اگر مقادیر در قالب یک آرایه باشند، ما یک نتیجه غیر عددی را به دست میآوریم. ما داریم درباره JavaScript صحبت میکنیم؛ پس چندین راه برای انجام این کار وجود دارند، اما بیایید از apply استفاده کنیم.
حال وقتی که ما از apply و تابع Math.max() استفاده میکنیم، نتیجه مد نظر را به دست میآوریم. همانطور که میدانیم، apply تمام مقادیر داخل آرایه را به عنوان آرگومانهای جداگانه میگیرد و سپس تابع max به آنها اعمال خواهد شد. این کار، بزرگترین مقدار موجود در آرایه را به ما میدهد.
یک نکته جالب که باید در اینجا به آن اشاره کنیم، این است که ما به جای this از null استفاده کردهایم. با توجه به این که آرگومان فراهم شده یک آرایه اعداد است، حتی اگر this معرفی شده باشد هم به یک آرایه اشاره خواهد داشت و ما نتیجه مشابهی را به دست خواهیم آورد. از این رو، در موارد این چنینی ما میتوانیم از null به جای this استفاده کنیم. این به ما نشان میدهد که آرگومان this در تابع apply، یک آرگومان اختیاری است.
Call
متد call() برای فراخوانی یک تابع با یک this داده شده و آرگومانهایی که به صورت جداگانه برای آن فراهم شدهاند، استفاده میشود. این یعنی ما میتوانیم هر تابعی را به صراحت و با مشخص کردن ارجاع این که this باید به تابع فراخوان اشاره داشته باشد، فراخوانی کنیم. این بسیار شبیه به apply بوده، و تنها تفاوت آن این است که apply آرگومانها را در قالب آرایه یا آبجکتهای شبیه به آرایه میگیرد، و در اینجا آرگومانها به طور جداگانه فراهم شدهاند.
سینتکس
مقدار برگشتی
نتیجه فراخوانی تابع با مقدار this و آرگومانهای مشخص شده.
توصیف
متد call برای این استفاده میشود که به یک تابع / آبجکت که به یک آبجکت مانند x تعلق دارد، اجازه دهیم فراخوانی شده، و یا به یک آبجکت دیگر مثلا y اختصاص داده شود.
مثالها
۱:
این مثالی از زنجیرهبندی constructor است. همانطور که میتوانیم ببینیم، در تمام توابع constructor مربوط به Product فراخوانی شده است، و ویژگیهای آبجکت Product با استفاده از call، به ترتیب با آبجکتهای Pizza وToy زنجیر شدهاند.
وقتی که نمونههای جدیدی از آبجکتهای Pizza و Toy ساخته میشوند، پارامترها به عنوان name (نام)، price (قیمت) و category (دسته) فراهم میشوند. category فقط در تعریف اعمال شده است، اما name و price همانطور که در آبجکت Product تعریف شده و اعمال شدهاند، با استفاده از constructor زنجیر شده این آبجکت اعمال شده میباشند. ما با کمی پیچ و خم، ما میتوانیم به وراثت برسیم.
۲:
در قطعه کد بالا ما یک تابع به نام sleep را تعریف کردیم. این تابع از یک آرایه تشکیل شده میباشد. این آرایه از عناصری تشکیل شده است که با استفاده از کلیدواژه this به ویژگیها دسترسی دارند. این ویژگیها در یک آبجکت جداگانه خارج از تابع تعریف شدهاند. تابع sleep با آبجکت obj به عنوان یک آرگومان فراخوانی شده است. همانطور که میتوانیم ببینیم، ویژگیهای obj به ترتیب در this.animal و this.sleepDuration تنظیم شدهاند، و ما یک جمله کامل را به عنوان خروجی دریافت میکنیم.
Bind
متد bind یک تابع جدید را میسازد که این تابع وقتی فراخوانی شود، کلیدواژه this را برابر با مقدار فراهم شده، به همراه یک توالی از آرگومانها دارد.
سینتکس
مقدار برگشتی
Bind یک کپی از توابع را با this و آرگومانهای عرضه شده بر میگرداند.
توصیف
تابع bind بسیار شبیه به تابع call بوده، و تفاوت اصلی آن در اینجاست که bind یک تابع جدید را بر میگرداند، اما call این کار را انجام نمیدهد. طبق گفته مشخصه ECMAScript 5، تابع برگردانده شده توسط bind نوع خاصی از آبجکت تابع بیگانه، به نام Bound function (BF) است. BF آبجکت تابع اصلی را جمعبندی میکند. فراخوانی BF، تابع جمعبندی شده داخل خود را اجرا میکند.
مثالها
۱:
در قطعه کد بالا، ما یک متغیر به نام x و یک آبجکت به نام module را تعریف کردهایم. این کد همچنین شامل یک ویژگی به نام x و یک ویژگی دیگر که مقدار متناظر آن یک تابع است، و این تابع مقدار x را بر میگرداند، میباشد.
وقتی که تابع getX فراخوانی میشود، این تابع مقدار x که داخل آبجکت تعریف شده است را بر میگرداند، نه x موجود در محدوده global.
یک متغیر دیگر داخل محدوده global تعریف شده است که تابع getX را از آبجکت module فراخوانی میکند. اما با توجه به این که متغیر مورد نظر در محدوده global است، this و getX به x اشاره دارند و از این رو مقدار 9 برگردانده میشود.
یک متغیر دیگر هم تعریف شده است که تابع قبلی را بر میگرداند، اما این بار تابع مذکور را با آبجکت module اتصال میدهد (bind میکند). این اتصال مقدار x داخل آبجکت را بر میگرداند. با توجه به اتصال، this موجود در تابع به مقدار x موجود در آبجکت اشاره دارد، نه x از نوع global. از این رو ما مقدار 91 را به عنوان خروجی دریافت میکنیم.
نتیجه گیری
حال که ما پایههای متدها را یاد گرفتهایم، شاید هنوز هم گیج شده باشید که چرا ۳ تابع مختلف داریم، و این توابع تقریبا کار مشابهی را انجام میدهند. برای واضحسازی این مفهوم، شما باید با موقعیتها و سناریوهای مختلف تمرین کنید، تا بتوانید به طور کامل یاد بگیرید که این توابع در کجا و چگونه میتوانند استفاده شوند. این توابع مطمئنا کد را تمیزتر و قویتر خواهند کرد.
دیدگاه و پرسش
در حال دریافت نظرات از سرور، لطفا منتظر بمانید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید