this در جاوااسکریپت به چه معناست ؟

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

به قطعه کد زیر نگاه کنید :
<!DOCTYPE html><html lang="en"><body><script>
 
    var cody = {
        living: true,
        age: 23,
        gender: 'male',
        getGender: function () { return cody.gender; }
    };
 
    console.log(cody.getGender()); // Logs 'male'.
 
</script></body></html>
حالا به درون تابع getGender نگاه کنید، ما به خاصیت gender از طریق یک نقطه ( cody.gender ) دسترسی پیدا کردیم، میتوانیم از this استفاده کنیم تا به شی cody دسترسی پیدا کنیم به خاطر اینکه this به شی cody اشاره میکند، به قطعه کد زیر توجه کنید :
<!DOCTYPE html><html lang="en"><body><script>
 
    var cody = {
        living: true,
        age: 23,
        gender: 'male',
        getGender: function () { return this.gender; }
    };
 
    console.log(cody.getGender()); // Logs 'male'.
 
</script></body></html>
This در this.gender استفاده شد، در قسمتی که تابع عملیات را انجام میدهد از طریق this به شی cody دسترسی پیدا کردیم، this میتواند پیچیده نیز شود، اما لازم نیست آن را زیاد پیچیده کنید، فقط به یاد داشته باشید، this در درون یک تابع استفاده میشود تا به شی ای که تابع را دربر گرفته است اشاره کند.
کلمه کلیدی this مانند متغیرهای دیگر رفتار میکند با این تفاوت که شما نمیتوانید به صورت عادی آن را مانند متغیرها تغییر بدهید و برخلاف متغیرها که در بین تابع ها به عنوان آرگومان ورودی یا خروجی گرفته یا فرستاده میشوند با this نمیتوانید همچین کاری کنید.

Value کلمه کلیدی this چگونه تعیین میشود ؟

Value کلمه کلیدی this بر اساس context تابع ایجاد میشود، خوب دقت کنید زیرا باید خوب به خاطر بسپارید، شی myObject در کد زیر یک خاصیت میدهد به اسم sayFoo که به تابع sayFoo اشاره میکند، زمانی که sayFoo از اسکوپ بالاتر فراخوانی میشود، this به شی window اشاره میکند، زمانی که به عنوان یک متد از myObject فراخوانی میشود، this به myObject اشاره میکند، به کد زیر توجه کنید :
<!DOCTYPE html><html lang="en"><body><script>
 
    var foo = 'foo';
    var myObject = { foo: 'I am myObject.foo' };
 
    var sayFoo = function () {
        console.log(this['foo']);
    };
 
    // Give myObject a sayFoo property and have it point to the sayFoo function.
    myObject.sayFoo = sayFoo;
 
    myObject.sayFoo(); // Logs 'I am myObject.foo'.
    sayFoo(); // Logs 'foo'.
 
</script></body></html>
در حقیقت، value کلمه کلیدی this بر اساس context مکانی که تابع در آن فراخوانی میشود مقداردهی میشود، myObject.sayFoo و sayFoo هردو به یک تابع مشخص اشاره میکنند، اما بر اساس اینکه context ئه sayFoo در کجا فراخوانی میشود، value کلمه کلیدی this مقدار دهی میشود.
اگر باعث یادگیری بیشتر شما میشود، این همان کد بالا است با این تفاوت که window نیز به صورت صریح استفاده شده است :
<!DOCTYPE html><html lang="en"><body><script>
 
    window.foo = 'foo';
    window.myObject = { foo: 'I am myObject.foo' };
 
    window.sayFoo = function () {
        console.log(this.foo);
    };
 
    window.myObject.sayFoo = window.sayFoo;
 
    window.myObject.sayFoo();
    window.sayFoo();
 
</script></body></html>
مقدار this بر اساس context تغییر میکند.

در تابع های تودرتو (nested) کلمه کلیدی this به شی ابتدایی اشاره میکند !

طریقه عملکر this هنگامی که درون یک تابع است و آن تابع درون یک تابع دیگر است فرق میکند، بر اساس ECMA 3 ، this مسیر خود را از دست میدهد و به شی بالایی اشاره میکند ( شی window در مرورگر ) بجای اینکه به شی تابع اشاره کند.
در قطعه کد زیر، this درون func2 و func3 قرار دارد و مسیر خود را از دست میدهد و به myObject اشاره نمیکند و به شی بالایی یا به اصطلاح فنی شی head اشاره میکند.
<!DOCTYPE html><html lang="en"><body><script>
 
    var myObject = {
        func1: function () {
            console.log(this); // Logs myObject.
            var func2 = function () {
                console.log(this) // Logs window, and will do so from this point on.
                var func3 = function () {
                    console.log(this); // Logs window, as it’s the head object.
                } ();
            } ();
        }
    }
 
    myObject.func1();
 
</script></body></html>
خبر خوب اینکه این مشکل در ECMAScript 5 اصلاح شده است، درحال حاضر باید به این مسئله آگاه باشید و هنگامی که درون توابع مختلف متغیرهای خود را جابجا میکنید طریقه عملکرد آن را بدانید.
قطعه کد زیر را در نظر بگیرید، هنگامی که یک تابع ناشناس را به foo.func1 بفرستیم چه اتفاقی می افتد ؟ زمانی که یک تابع ناشناس درون foo.func1 فراخوانی شود ( یک تابع درون تابع دیگر ) مقدار this درون تابع ناشناس به شی foo اشاره میکند :
<!DOCTYPE html><html lang="en"><body><script>
 
    var foo = {
        func1: function (bar) {
            bar(); // Logs window, not foo.
            console.log(this); // The this keyword here will be a reference to the foo object.
        }
    }
 
    foo.func1(function () { console.log(this) });
 
</script></body></html>
هرگز فراموش نکنید : مقدار this همیشه به شی head اشاره میکند زمانی که تابع میزبان توسط یک تابع دیگر محصور شده باشد، یکبار دیگر تکرار میکنم، این عملیات در ECMAScript 5 اصلاح شده است.

در اسکوپ های زنجیره ای چه اتفاقی می افتد ؟

به راحتی میتوانید از اسکوپ های زنجیره ای نیز استفاده کنید، بر اساس کد زیر، یک متغیر مانند that داریم، با توجه به کد و کامنت های درون آن داریم :
<!DOCTYPE html><html lang="en"><body><script>
 
var myObject = {
    myProperty: 'I can see the light',
    myMethod : function(){
        var that = this; // Store a reference to this (myObject) in myMethod scope.
        var helperFunction = function() { // Child function.
            // Logs 'I can see the light' via scope chain because that = this.
            console.log(that.myProperty); // Logs 'I can see the light'.
            console.log(this); // Logs window object, if we don't use "that".
        }();
    }
}
 
myObject.myMethod(); // Invoke myMethod.
 
</script></body></html>

کنترل کردن مقدار this توسط ()call یا ()apply

مقدار this به صورت نرمال توسط context تابعی که فراخوانی میشود تعیین میشود، اما توسط ()apply و ()call میتوانید مقدار this را هنگامی که فراخونی میشود به مقادیر مختلفی ارجاع دهید، به صورت فکر کنید که تابع X را فراخوانی میکنیم اما به تابع میگوییم که شی Z را به عنوان مقدار this قرار بده و از این طریق مقدار this را override میکنیم.
در مثال بعدی، یک شی و یک تابع میسازیم، سپس تابع را از طریق call() فراخوانی میکنیم و بنابراین مقدار this درون تابع از myObject به عنوان context استفاده میکند :
<!DOCTYPE html><html lang="en"><body><script>
 
    var myObject = {};
 
    var myFunction = function (param1, param2) {
        // Set via call(), 'this' points to myObject when function is invoked.
        this.foo = param1;
        this.bar = param2;
        console.log(this) // Logs Object {foo = 'foo', bar = 'bar'}
    };
 
    myFunction.call(myObject, 'foo', 'bar'); // Invoke function, set this value to myObject.
 
    console.log(myObject) // Logs Object {foo = 'foo', bar = 'bar'}
 
</script></body></html>
در مثال قبلی از call() استفاده کردیم اما همچنین میتوانیم از apply() نیز استفاده کنیم، تفاوت بین این دو در تفاوت بین پاس دادن متغیرها در توابع است :
<!DOCTYPE html><html lang="en"><body><script>
 
    var myObject = {};
 
    var myFunction = function (param1, param2) {
        // Set via apply(), this points to myObject when function is invoked.
        this.foo = param1;
        this.bar = param2;
        console.log(this) // Logs Object {foo = 'foo', bar = 'bar'}
    };
 
    myFunction.apply(myObject, ['foo', 'bar']); // Invoke function, set this value.
 
    console.log(myObject) // Logs Object {foo = 'foo', bar = 'bar'}
 
</script></body></html>

استفاده از this درون یک سازنده ( constructor ) تعریف شده توسط کاربر

زمانی که یک تابع توسط new فراخوانی میشود، مقدار this به نمونه ( instance ) اشاره میکند، به بیان دیگر، در تابع constructor میتوانیم از طریق this قبل از اینکه شی ساخته شود به آن دسترسی پیدا کنیم، در این مثال، مقدار this میتواند مانند call() یا apply() تغییر کند. در مثال زیر، یک constructor از تابع person میسازیم و از this استفاده میکنیم تا به شی ای که ساخته ایم اشاره کنیم، زمانی که یک instance از Person ساخته شد، this.name به شی ای که تازه ساخته شد اشاره میکند و خاصیت name را میگیرد :
<!DOCTYPE html><html lang="en"><body><script>
 
    var Person = function (name) {
        this.name = name || 'john doe'; // this will refer to the instance created.
    }
 
    var cody = new Person('Cody Lindley'); // Create an instance based on the Person constructor.
 
    console.log(cody.name); // Logs 'Cody Lindley'.
 
</script></body></html>
زمانی که تابع constructor توسط new فراخونی میشود this به شی ای که به صورت پیشفرض باید اشاره کند، اشاره میکند، اگر از new استفاده نمیکردیم، مقدار this به context ای که هنگام فراخوانی Person ایجاد میشد اشاره میکرد، به مثال زیر توجه کنید :
<!DOCTYPE html><html lang="en"><body><script>
 
    var Person = function (name) {
        this.name = name || 'john doe';
    }
 
    var cody = Person('Cody Lindley'); // Notice we did not use 'new'.
 
    console.log(cody.name); // Undefined. The value is actually set at window.name
 
    console.log(window.name); // Logs 'Cody Lindley'.
 
</script></body></html>

نتیجه گیری

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

محمد یه دانشجوی فناوری اطلاعات هست که از سال 92 فعالیتش رو شروع کرد، در حال حاضر در زمینه ی برنامه نویسی تحت وب و اندروید و شبکه های ارتباطی سیسکو فعالیت میکنه .

نظرات و سوالات کاربران

ارسال پاسخ iman313
iman313
جمعه ۰۷ آبان ۱۳۹۵ ۰۹:۲۲
ایول عالیه ادامه بدین عاشقتونم
ارسال پاسخ رضا
رضا
شنبه ۰۳ بهمن ۱۳۹۴ ۱۰:۱۵
سلام خسته نباشین , میشه یه مثال دیگه در مورد aplay and call بزنید؟