فراخوانی و صدا زدن (call & invoke) توابع در JavaScript
فراخوانی توابع
همانطور که می دانید کدهای داخل یک تابع در جاوا اسکریپت اجرا نمی شوند مگر آنکه تابع فراخوانی شود. «صدا زدن» و یا «فراخوانی» که در انگلیسی به ترتیب معادل call a function و invoke a function هستند با یکدیگر هیچ تفاوتی ندارند و شما می توانید از هر کدام که تمایل داشتید استفاده کنید.
مثال زیر یک نوع ساده از فراخوانی توابع در جاوا اسکریپت است:
<!DOCTYPE html>
<html>
<body>
<h2>JavaScript Functions</h2>
<p>The global function (myFunction) returns the product of the arguments (a ,b):</p>
<p id=”demo”></p>
<script>
function myFunction(a, b) {
return a * b;
}
document.getElementById(“demo”).innerHTML = myFunction(10, 2);
</script>
</body>
</html>
نکته: همانطور که مشخص است تابع بالا متعلق به هیچ شیء خاصی نیست اما این ظاهر قضیه است. در جاوا اسکریپت همیشه یک شیء سراسری و پیش فرض وجود دارد. در اسناد HTML شیء سراسری همان صفحه ی HTML است بنابراین تابعی که بالاتر نوشته ایم متعلق به شیء صفحه ی HTML است. اما زمانی که این سند HTML درون یک مرورگر قرار می گیرد، شیء اصلی همان شیء window می باشد بنابراین می توان کد بالا را به صورت زیر نوشت:
<!DOCTYPE html>
<html>
<body>
<h2>JavaScript Functions</h2>
<p>Global functions automatically become window methods. Invoking myFunction() is the same as invoking window.myFunction().</p>
<p id=”demo”></p>
<script>
function myFunction(a, b) {
return a * b;
}
document.getElementById(“demo”).innerHTML = window.myFunction(10, 2);
</script>
</body>
</html>
و میبینیم که myFunction دقیقا همان window.myFunction است.
اگر چه این روش، روش محبوب و ساده ی فراخوانی و ایجاد توابع است اما بهترین راه نیست چرا که در برخی از موارد متغیرهای سراسری، متدها یا توابع می توانند به نام هایی که از قبل در شیء سراسری وجود دارند، همسان باشند و باعث ایجاد باگ در برنامه ی شما شوند.
کلیدواژه ی this
به شیء ای اشاره می کند که صاحب کد فعلی است. بنابراین اگر این کلیدواژه را در یک تابع به کار ببریم، this
به شیء ای برمیگردد که صاحب این تابع است.
سوال: اگر کد ما بدون شیء خاصی باشد، کلیدواژه ی this
چه چیزی را نشان می دهد؟
پاسخ: اگر تابع یا کدهای شما درون شیء خاصی نباشند، کلیدواژه ی this
به شیء سراسری اشاره می کند. به طور مثال می توانیم کد زیر را بنویسیم تا شیء اصلی مشخص شود:
<!DOCTYPE html>
<html>
<body>
<h2>JavaScript Functions</h2>
<p>In HTML the value of <b>this</b>, in a global function, is the window object.</p>
<p id=”demo”></p>
<script>
var x = myFunction();
function myFunction() {
return this;
}
document.getElementById(“demo”).innerHTML = x;
</script>
</body>
</html>
شیء [object Window] به ما برگردانده می شود.
توجه: استفاده از [object Window] به عنوان یک متغیر باعث crash و متوقف شدن کامل برنامه ی شما می شود. به عنوان قانونی کلی به شما می گویم که هیچ گاه به توابع، اشیاء و به طور کلی کدهای از پیش نوشته شده ی جاوا اسکریپت دست نزنید.
فراخوانی توابع به عنوان متد
همانطور که می دانید می توانیم توابع جاوا اسکریپت را به عنوان متدهای اشیاء مختلف تعریف کنیم. در چنین حالتی باید تعریف تابع را درون شیء مورد نظر قرار دهیم:
<!DOCTYPE html>
<html>
<body>
<h2>JavaScript Functions</h2>
<p>myObject.fullName() will return John Doe:</p>
<p id=”demo”></p>
<script>
var myObject = {
firstName:”Alireza”,
lastName: “Sh”,
fullName: function() {
return this.firstName + ” ” + this.lastName;
}
}
document.getElementById(“demo”).innerHTML = myObject.fullName();
</script>
</body>
</html>
در این حالت کلیدواژه ی this
به شیء صاحب کد یعنی myObject اشاره می کند. اگر شیء بالا را تغییر دهیم و به جای آن کد زیر را قرار دهیم:
var myObject = {
firstName:”Alireza”,
lastName: “Sh”,
fullName: function () {
return this;
}
خروجی ما [object Object] خواهد بود که نشان دهنده ی این است که صاحب این متد همان myObject است.
فراخوانی تابع از طریق Function Constructor
به زبان ساده می گویم: اگر فراخوانی یک تابع با کلیدواژه ی new
انجام شود، این فراخوانی از طریق constructor بوده است. در ظاهر به نظر می رسد که یک تابع دیگر می سازید اما از آن جا که توابع جاوا اسکریپتی از نوع اشیاء هستند، یک شیء جدید می سازید:
<!DOCTYPE html>
<html>
<body>
<h2>JavaScript Functions</h2>
<p>In this example, myFunction is a function constructor:</p>
<p id=”demo”></p>
<script>
function myFunction(arg1, arg2) {
this.firstName = arg1;
this.lastName = arg2;
}
var x = new myFunction(“Alireza”,”Sh”)
document.getElementById(“demo”).innerHTML = x.firstName;
</script>
</body>
</html>
در این حالت، کلیدواژه ی this
در یک constructor مقداری ندارد بلکه مقدار this
همان شیء جدیدی است که هنگام فراخوانی تابع ساخته می شود.
استفاده از تابع ()call
یکی از مواردی که جا دارد در مورد آن صحبت کنیم متد ()call
است. با استفاده از این متد می توانید متدهایی داشته باشید که روی اشیاء دیگر اجرا می شوند.
همانطور که میدانید در زبان جاوا اسکریپت تمام توابع، متدهای شیء خاصی هستند. به شکلی که اگر تابعی شیء خاص خود را نداشته باشد، بخشی از شیء سراسری جاوا اسکریپت خواهد بود.
حالا کاری که متد ()call
برای ما انجام می دهد این است که شیء مورد نظر را به عنوان پارامتر دریافت کرده و متد خاصی را روی آن اجرا می کند.
سوال: این قابلیت به چه درد ما می خورد؟
پاسخ: به خودی خود بی فایده به نظر می رسد اما اگر خوب دقت کنید متوجه می شوید که یک شیء می تواند از طریق ()call
از متدی استفاده کند که متعلق به شیء دیگری است! بنابراین می توانید از زیاده نویسی های زیادی جلوگیری کرده و در عین حال در وقت خود صرفه جویی کنید. تصور کنید که متدهای یک شیء را روی هر شیء ای که خواستید پیاده سازی کنید! این تابع از توابع بسیار به درد بخور جاوا اسکریپت است.
برای مثال سه شیء تعریف می کنیم و نام آن ها را person و person1 و person2 گذاشته و در شیء person یک متد به نام fullName تعریف می کنیم. حالا می خواهیم کاری کنیم که شیء person1 بدون داشتن متدِ fullName بتواند از آن استفاده کند:
<!DOCTYPE html>
<html>
<body>
<h2>JavaScript Functions</h2>
<p>This example calls the fullName method of person, using it on person1: </p>
<p id=”demo”></p>
<script>
var person = {
fullName: function() {
return this.firstName + ” ” + this.lastName;
}
}
var person1 = {
firstName:”Alireza”,
lastName: “Sh”
}
var person2 = {
firstName:”Ali”,
lastName: “Re”
}
var x = person.fullName.call(person1);
document.getElementById(“demo”).innerHTML = x;
</script>
</body>
</html>
همچنین با تغییر پارامتر call به کد زیر می توانیم آن را روی شیء person2 نیز اجرا کنیم:
person.fullName.call(person2);
بنابراین می توانید با دستور ()call
یک متد را روی شیء دیگری فراخوانی کنید!
همچنین دنبال کنید Properties (خواص) در اشیاء JavaScript اینجا کلیک کنید.