در زبان برنامه نویسی جاوااسکریپت، توابع جزو اشیاء هستند، و توابع جاوااسکریپت دارای متد و ویژگی هستند.
call() و apply() دو متد پیشفرض توابع جاوااسکریپت هستند. هر دو متد توانایی فراخوانی توابع رو دارند و در هر دومتد باید آبجکت والد رو به عنوان پارامتر اول داشته باشیم.
برای شروع کار مثالی ساده رو باهم بررسی کنیم :
کد:
function myFunction(a, b) {
    return a * b;
}
myObject = myFunction.call(myObject, 10, 2);     // return 20
و برای apply() :
کد:
function myFunction(a, b) {
    return a * b;
}
myArray = [10, 2];
myObject = myFunction.apply(myObject, myArray);  //  return 2
اگر دقت کنید هر دو متد، myObject رو به عنوان والدشون و پارامتر اول قرار دادن و تنها تفاوت این دو تابع در نحوه‌ی ارسال آرگومان ها می باشد که در متد call به صورت آرگومان‌هایی تکی ارسال می‌شوند ولی در apply میتوان به صورت آریه ارسال کرد.
باید دقت کنیم در حالت strict mode پارامتر اولی که ارسال میشه مقدار this رو در تابع فراخوانی شده خواهد داشت حتی در صورتیکه آبجکت نباشد. در حالت non-strict mode اگر پارامتر اول null و یا undefined باشد، با global object ریپلیس می‌شود.

Strict mode از ECMA SCRIPTورژن 5 اعمال شد و در اینترنت اکسپلورر 10 ، فایرفاکس 4 ، کروم ورژن 13 ، سافاری ورژن 5.1 و اپرا ورژن 12 به بعد ساپورت میشه. در این حالت تمام سینتکس های جاوااسکریپت باید رعایت بشه برای مثال در حالت strict mode ما دیگه نمیتونیم متغیری رو بدون اعلان و تعریفش استفاده کنیم و Error خواهیم داشت و ....
برای مطالعه بیشتر این موضوع میتونید لینک "JavaScript Use Strict" رو در سایت " W3schools " مطالعه نمائید.

این نکته رو به یاد داشته باشیم که با استفاده از این دو متد ما میتونیم مقدار this رو در تابعی که فراخوانی میکنیم ست کنیم.

مواردی که تا الان ذکر کردیم کلیاتی بودند برای اینکه با موضوع تا حدودی درگیر بشید و حالا بیایید با هم بیشتر موضوع رو باز کنیم و بحث کنیم

ادامه بحث رو با مثالی دیگه ادامه بدیم :
کد:
var x = 10;
function f()
{
    alert(this.x);
}
f();
در اینجا ما یک تابع gloabal داریم به نام f که درون این تابع کلمه‌ی کلیدی this به مقدار x اشاره میکنه اما نکته اینجاست که ما به هیچ تابعی اشاره نمیکنیم و مقداری رو از میان آبجکت‌ها فراخوانی نمیکنیم، پس رفرنس ما برای فراخوانی کدوم آبجکته؟ و چطور تشخیص میده که مقدار x رو از کجا فراخوانی کنه؟! بله درسته! gloabal object رفرنس ما خواهد بود و gloabal object مکانیه که ما x رو در اون تعریف کردیم. پس مقداری که در آخر برای ما نمایش داده شود مقدار 10 خواهد بود.

با بررسی مثال زیر موضوع جذابتر خواهد شد، let's go
کد:
var x = 10;
var o = { x: 15 };
 
function f()
{
    alert(this.x);
}
f();  // ?
f.call(o); // ??
مطمئنا حدس زدید که جای علامت سوال اول مقدار 10 قرار خواهد گرفت چونکه رفرنس ما gloabal object می‌باشد.
مقدار دوم (؟؟) هم مقدار 15 خواهد بود چونکه ما با استفاده از متد call به آبجکت o اشاره میکنیم و مقدار xی که در آبجکت o تعریف شده است مقدار 15 می‌باشد. پس همانطور که دقت کردید ما میتونیم مقدار this را به این نحو تغییر بدیم.

همچنین میتونیم مقداری رو با استفاده از متد call ارسال کنیم :
کد:
var x = 10;
var o = { x: 15 };
function f(message)
{
    alert(message);
    alert(this.x);
}
f("invoking f"); // invoking f 10
f.call(o, "invoking f via call"); // invoking f via call 15
متد apply دقیقا مانند متد Call عمل میکنه با این تفاوت که با استفاده از متد apply میتونیم مقداری رو به عنوان آرایه ارسال کنیم :
کد:
var x = 10;
var o = { x: 15 };
function f(message)
{
    alert(message);
    alert(this.x);
}
 
f("invoking f");
f.apply(o, ["invoking f through apply"]);
مثالی پیچیده تر :
کد:
var o = { x: 15 };
function f1(message1)
{
    alert(message1 + this.x);
}
function f2(message1, message2)
{
    alert(message1 + (this.x * this.x) + message2);
}
function g(object, func, args)
{
    func.apply(object, args);
}
g(o, f1, ["the value of x = "]);
g(o, f2, ["the value of x squared = ", ". Wow!"]);
همانطور که در مثال بالا میبینید میشه گفت کمی کدها پیچیده شده و ما میتونیم به صورت فانکشنال و بهنه تر بنویسیم و به این صورت عمل میکنیم :
اگر یادتون باشه آرگومان‌هایی که به تابع ارسال میشن رو میتونیم مقدار length رو بگیریم و تعداد اونها رو بدست بیاریم برای مثال :
کد:
function f(message)
{
    for(var i = 1; i < arguments.length; i++)
    {
        message += arguments[i];
    }
    alert(message);
}
// this will say "Hello"
f("H", "e", "l", "l", "o");
همانطور که مشاهده میکنید با محاسبه‌ی length آرگومانهایی که ارسال شده اند میتونیم برنامه رو به صورتی بهینه بنویسیم.
اکنون با هم مثال قبلی رو به صورت زیر بازنویسی میکنیم :
کد:
var o = { x: 15 };
function f(message1, message2)
{
    alert(message1 + (this.x * this.x) + message2);
}
function g(object, func)
{          
    // arguments[0] == object
    // arguments[1] == func 
     
    var args = []; // empty array
    // copy all other arguments we want to "pass through"
    for(var i = 2; i < arguments.length; i++)
    {
        args.push(arguments[i]);
    }
    func.apply(object, args);
}
g(o, f, "The value of x squared = ", ". Wow!");
ما در این پارت آموزشی مفاهیم call و apply رو به صورت تئوری توضیح دادیم و برای اینکه درک این موضوع براتون تثبیت بشه لازمه که در پروژه هایی که دارید از این متدها استفاده کنید. امیدوارم به درک این موضوع کمکی کرده باشیم .

و نکته‌ی مهم اینکه مثل همیشه از تک تک لحظاتتون مخصوصا موقع کدنویسی لذت ببرید.
شاد باشید