رمزگشایی کلمه کلیدی «این» در جاوا اسکریپت

سردرگمی زیادی در اطراف وجود دارد this
کلمه کلیدی در جاوا اسکریپت راه this
شرح داده شده در اسناد وب رسمی MDN بسیار بصری نیست. اگر شما هم چنین احساسی دارید، بیایید در مورد آن بیاموزیم this
کلمه کلیدی با استفاده از چند مثال عملی
چیست this
?
را this
کلمه کلیدی به زمینه ای اشاره دارد که یک قطعه کد باید در آن اجرا شود. اگر موارد زیر را در مرورگر خود وارد کنسول کنیم چه چیزی به دست می آید؟
console.log(this)
نتیجه اجرای کد بالا کل مرورگر است Window
هدف – شی. اگر به جای آن آن را در Node اجرا کنید، آن را دریافت خواهید کرد جهانی است هدف – شی. از این رو، this
نشان دهنده زمینه جایی است که کد تعریف شده است.
بیایید نگاهی به یک مثال بیندازیم. در زیر یک شی به نام داریم student
و در داخل شی تابعی به نام تعریف خواهیم کرد testFunction
.
const student = {
name: "Jon",
phone: 415887231,
testFunction: function () {
console.log(this);
},
};
student.testFunction();
خروجی:
{
name: "Jon"
phone: 415887231
testFunction: ƒ testFunction()
}
ما در حال ورود به سیستم کنسول هستیم this
از داخل testFunction
. از آنجا که testFunction
در داخل تعریف شده است student
شی ما کل را دریافت می کنیم student
شی به عنوان خروجی را student
شیء زمینه ای است که تابع در آن تعریف می شود.
this
و strict
حالت در Node
هنگامی که از حالت سخت در Node استفاده می کنید، رفتار از this
متفاوت است. مثال زیر این رفتار را نشان می دهد.
'use strict';
// Top level
console.log(this); // {}
function strictFunction() {
console.log(this); // undefined
}
strictFunction();
در سطح بالا در یک ماژول this
هنوز است شی جهانی. با این حال، در داخل یک تابع this
اکنون است تعریف نشده.
چرا این می تواند مفید باشد؟ موارد استفاده زیادی از strict
حالت در ادامه به برخی از آنها اشاره می شود.
اجتناب از جهانی های تصادفی:
'use strict';
x = 10; // ReferenceError: x is not defined
اختصاص دادن یک مقدار به یک متغیر اعلام نشده، یک متغیر سراسری ایجاد می کند. حالت سختگیرانه از این امر جلوگیری می کند.
موارد تکراری در لفظ شیء:
'use strict';
var obj = {
prop: 1,
prop: 2 // SyntaxError: Duplicate data property in object literal
};
حالت سختگیرانه برای نامهای خصوصیات تکراری در لفظ شیء خطایی ایجاد میکند.
گرفتن خطاهای بی صدا:
در حالت غیر دقیق، تخصیص یک مقدار به یک ویژگی غیرقابل نوشتن هیچ کاری بیصدا نمیکند. در حالت سخت، خطا می دهد.
// non strict mode
var obj = {};
Object.defineProperty(obj, 'x', { value: 42, writable: false });
obj.x = 9; // Fails silently, obj.x remains 42
console.log(obj.x); // 42
'use strict';
var obj = {};
Object.defineProperty(obj, 'x', { value: 42, writable: false });
obj.x = 9; // TypeError: Cannot assign to read only property 'x' of object '#
چگونه می کند this
در داخل توابع منظم و توابع پیکانی رفتار کنید؟
درک چگونگی this
رفتار در سناریوهای مختلف برای نوشتن کد جاوا اسکریپت تمیز و قابل پیش بینی مهم است، به خصوص زمانی که با متدهای شی و پاسخ به تماس ها سر و کار داریم.
مثال زیر رفتار this
در یک تابع تماس معمولی که در داخل یک تابع تعریف شده است.
const student = {
name: "Jon Doe",
printAllCourses: function () {
const subjects = ["cs-101", "cs-202", "econ-101"];
subjects.forEach(function (sub) {
console.log(sub);
console.log("Student Name", this.name);
});
},
};
student.printAllCourses();
// outputs
/**
cs-101
Student Name undefined
cs-202
Student Name undefined
econ-101
Student Name undefined
**/
به عملکرد برگشت به تماس توجه کنید forEach
در حال تلاش برای دسترسی به name
دارایی اما در حال بازگشت است تعریف نشده.
حالا تابع callback را به یک تابع فلش تبدیل کنید و دوباره کد را اجرا کنید.
const student = {
name: "Jon Doe",
printAllCourses: function () {
const subjects = ["cs-101", "cs-202", "econ-101"];
subjects.forEach((sub) => {
console.log(sub);
console.log("Student Name", this.name);
});
},
};
student.printAllCourses();
// outputs
/**
cs-101
Student Name Jon Doe
cs-202
Student Name Jon Doe
econ-101
Student Name Jon Doe
**/
توجه داشته باشید که این بار می تواند همانطور که انتظار می رود به ویژگی name دسترسی پیدا کند.
در واقع اینجا چه اتفاقی می افتد؟
this
داخل یک تابع منظم بستگی به نحوه فراخوانی تابع دارد. هنگامی که یک تابع معمولی به عنوان پاسخ به تماس استفاده می شود، فقط در آن صورت this
به شی جهانی اشاره دارد (window
در مرورگرها)، که در مثال بالا وجود دارد. از طرف دیگر، اگر تابع به عنوان یک تابع فراخوانی فراخوانی نشود، می تواند با استفاده از ویژگی های اشیاء والد دسترسی پیدا کند this
. بنابراین، اساسا، یک تابع فراخوان همیشه به عنوان تابعی در نظر گرفته می شود که در زمینه جهانی تعریف شده است.
از سوی دیگر، توابع پیکان، خود را ندارند this
متن نوشته. در عوض از نظر لغوی ارث می برند this
از کد اطراف این به سادگی به این معنی است که تابع فلش به خصوصیات شیئی که در آن تعریف شده است دسترسی دارد this
داخل یک فلش تابع همان است this
خارج از تابع فلش
const student = {
name: "Jon Doe",
printAllCourses: function () {
const subjects = ["cs-101", "cs-202", "econ-101"];
console.log("outside arrow func", this); // this here is the same this inside the callback arrow function below
subjects.forEach((sub) => {
console.log("inside arrow func", this); // same this as above
});
},
};
student.printAllCourses();
سلام، اگر از این پست لذت می برید و می خواهید موارد بیشتری را مشاهده کنید، فراموش نکنید که من را در dev.to دنبال کنید. ایکس یا لینکدین
چگونه می کند this
در زمینه کلاس es6 کار کنید؟
در کلاس های ES6، this
کلمه کلیدی در مقایسه با توابع سنتی جاوا اسکریپت قابل پیش بینی تر و سازگارتر است. هنگام استفاده از this
در داخل متدهای یک کلاس، به طور کلی به نمونه کلاسی که متد در آن فراخوانی شده است اشاره دارد.
یک کلاس ES6 ساده را در نظر بگیرید:
class Person {
constructor(name) {
this.name = name;
}
printName() {
console.log(this.name);
}
}
const person = new Person('Alice');
person.printName(); // Outputs: Alice
در مثال this
درون constructor
متد به نمونه جدیدی از کلاس در حال ایجاد اشاره دارد.
this
درون printName
روش به نمونه ای اشاره دارد Person
کلاسی که در آن printName
روش نامیده شد.
حال بیایید نگاهی به مثالی بیندازیم که مشکلات احتمالی را هنگام استفاده از متدهای کلاس بهعنوان بازگشت تماس و نحوه رسیدگی به آنها نشان میدهد:
class Person {
constructor(name) {
this.name = name;
}
printName() {
console.log(this.name);
}
printNameDelayed() {
setTimeout(function() {
console.log(this.name);
}, 1000);
}
printNameDelayedWithArrow() {
setTimeout(() => {
console.log(this.name);
}, 1000);
}
printNameDelayedWithBind() {
setTimeout(function() {
console.log(this.name);
}.bind(this), 1000);
}
}
const person = new Person('Bob');
person.printName(); // Outputs: Bob
person.printNameDelayed(); // Outputs: undefined (or error in strict mode)
person.printNameDelayedWithArrow(); // Outputs: Bob
person.printNameDelayedWithBind(); // Outputs: Bob
توجه کنید، در printNameDelayed
تابع فراخوانی را به روش ارسال کنید setTimeout
یک تابع منظم است، بنابراین this
داخل آن به مصداق اشاره نمی کند Person
. در عوض، به شی جهانی (یا undefined
در حالت سختگیرانه).
استفاده از یک تابع فلش به عنوان پاسخ تماس، حفظ می کند this
زمینه از روش محصور کردن، بنابراین this
اشاره به نمونه از Person
. را printNameDelayedWithArrow
یک راه حل ممکن برای مشکل برگشت تماس است.
راه دیگر برای حل این مشکل برگشت از طریق اتصال است. که در printNameDelayedWithBind
ما به صراحت تابع callback را به آن متصل می کنیم this
. آن را تضمین می کند this
در داخل callback اشاره به نمونه از Person
.
کلمات پایانی
امیدوارم این مقاله درک بهتری از این موضوع به شما داده باشد this
.
به این به عنوان فریبکار شیطانی جاوا اسکریپت فکر کنید – که همیشه شما را سرپا نگه می دارد. اما اکنون، شما در حال شوخی هستید. به آزمایش خود ادامه دهید و به زودی این فرد مورد اعتماد شما خواهد بود، نه دشمن شما.
بنابراین دفعه بعد که کسی می گوید جاوا اسکریپت گیج کننده است، فقط چشمک بزنید و بگویید: “من دقیقا می دانم چه کسی this
است!» برو و فتح کن، و باشد this
با تو بودن!
اگر از این پست لذت بردید من را دنبال کنید ایکس یا لینکدین