מילת המפתח this
מתייחסת לערך של האובייקט שמקושר אל
בזמן הקריאה. כלומר, הערך שלו משתנה בהתאם
קריאה לפונקציה כשיטה, כפונקציה עצמאית או כפונקציה
constructor.
כשמתבצעת קריאה לפונקציה, היא יוצרת מופע של מילת המפתח this
שמאחוריה
את הסצנות בתור התייחסות לאובייקט שמכיל את הפונקציה הזו,
גישה למאפיינים ולשיטות המוגדרים לצדה מתוך ההיקף שלה.
העבודה עם this
דומה בכמה דרכים לעבודה עם משתנה מוצהר
עם const
. כמו קבוע, לא ניתן להסיר את this
ולא ניתן להסיר את הערך שלו
הוקצתה מחדש, אבל השיטות והמאפיינים של האובייקט שמילת המפתח this
מכילה ניתנים לשינוי.
קישור גלובלי
מחוץ לפונקציה או להקשר של אובייקט, this
מתייחס אל
המאפיין globalThis
, שהוא הפניה לאובייקט הגלובלי ברוב המקרים
בסביבות JavaScript. בהקשר של סקריפט שמופעל בדפדפן אינטרנט,
האובייקט הגלובלי הוא האובייקט window
:
this;
> Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, ...}
ב-Node.js, globalThis
הוא האובייקט global
:
$ node
Welcome to Node.js v20.10.0.
Type ".help" for more information.
> this
<ref *1> Object [global] {
...
}
מחוץ למצב המחמיר, this
מתייחס גם לאובייקט הגלובלי בתוך אובייקט נפרד
של הפונקציה, כי ההורה Window
הוא האובייקט ש"הבעלים שלו" בפועל
את הפונקציות האלה.
function myFunction() {
console.log( this );
}
myFunction();
> Window {...}
(function() {
console.log( this );
}());
> Window {...}
כשמשתמשים במצב מחמיר, ל-this
יש את הערך undefined
בתוך נכס נפרד
פונקציה:
(function() {
"use strict";
console.log( this );
}());
> undefined
לפני ההשקה של המצב המחמיר, צריך להגדיר ערך של null
או undefined
עבור this
יוחלף בהפניה לאובייקט הגלובלי. יכול להיות שתראו לפעמים
קישור גלובלי נקרא "ברירת מחדל לקישור" בגלל ההתנהגות הקודמת הזאת.
קישור מרומז
כשקוראים לפונקציה כשיטה של אובייקט, נמצא בתוך מכונה של this
ש-method מתייחס לאובייקט שמכיל את ה-method, שמעניק גישה ל-
ולצידה:
let myObject = {
myValue: "This is my string.",
myMethod() {
console.log( this.myValue );
}
};
myObject.myMethod();
> "This is my string."
יכול להיות שהערך של this
תלוי באופן שבו פונקציה
מגדירים את האובייקט המקיף. במקום זאת, ההקשר של הערך של this
הוא
ההקשר הנוכחי של הביצוע. במקרה הזה, הקשר הביצוע הוא
האובייקט myObject
שולח קריאה ל-method myMethod
, לכן myObject
הוא הערך
עבור this
. הדבר עשוי להיראות כמו טכניקה בהקשר של
אבל לשימושים מתקדמים יותר ב-this
, זו הבחנה מהותית
חשוב לזכור.
באופן כללי, צריך להשתמש ב-this
בדרכים שלא מצפה לקבל את הקוד שמסביב
לכל מבנה מסוים. היוצאת מן הכלל לכלל הזה היא ES5
פונקציות חיצים.
this
בפונקציות חץ
בפונקציות חץ,
this
הופך לקישור ב-
סביבה מתוחכמת באופן מילוני. המשמעות היא
this
בפונקציית חץ מתייחס לערך של this
בפונקציה
ההקשר המקיף הקרוב ביותר:
let myObject = {
myMethod() { console.log( this ); },
myArrowFunction: () => console.log( this ),
myEnclosingMethod: function () {
this.myArrowFunction = () => { console.log(this) };
}
};
myObject.myMethod();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }
myObject.myArrowFunction();
> Window {...}
בדוגמה הקודמת, myObject.myMethod()
מתעד את myObject
כאובייקט
ש"הבעלים של" ה-method הזה, אבל myObject.myArrowFunction()
מחזירה globalThis
(או undefined
), כי המופע של this
בתוך פונקציית החץ
מתייחס במקום זאת להיקף המקיף הגבוה ביותר.
בדוגמה הבאה, הפונקציה myEnclosingMethod
יוצרת פונקציית חץ
שמכיל את האובייקט כשהוא מופעל. המופע של this
בתוך
פונקציית החץ מתייחסת עכשיו לערך של this
שבתוך התו המקיף
שהיא השיטה שמכילה את פונקציית החץ. כי
הערך של this
שבתוך myEnclosingMethod
מתייחס ל-myObject
, אחרי
מגדירים את פונקציית החץ, this
שבתוך פונקציית החץ מתייחס גם
myObject
:
let myObject = {
myMethod() { console.log( this ); },
myEnclosingMethod: function () {
this.myArrowFunction = () => { console.log(this) };
}
};
myObject.myEnclosingMethod();
myObject.myArrowFunction();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }
קישור מפורש
קישור משתמע מטפל ברוב התרחישים לדוגמה לעבודה עם this
. אבל,
ייתכן לפעמים שיהיה צורך בערך של this
כדי לייצג הפעלה ספציפית
ולא על ההקשר המשוער. להמחשה, אם מעט מיושן,
הדוגמה פועלת עם this
בתוך פונקציית הקריאה החוזרת של setTimeout
,
כי לקריאה החוזרת הזו יש הקשר ביצוע ייחודי:
var myObject = {
myString: "This is my string.",
myMethod() {
console.log( this.myString );
}
};
myObject.myMethod();
> "This is my string."
setTimeout( myObject.myMethod, 100 );
> undefined
למרות שהמחסור הספציפי הזה של setTimeout
טופל מאז על ידי
תכונות אחרות, בעיות דומות של "אובדן" הכתובת this
טופלה בעבר
על ידי יצירת הפניה מפורשת לערך של this
במסגרת
את ההקשר הרצוי. מדי פעם עשויים להופיע מופעים של this
שהוקצו
למשתנה באמצעות מזהים כמו that
, self
או _this
בגרסה הקודמת
ב-codebases. אלו מוסכמות נפוצות לגבי מזהים למשתנים שמכילים
עבר ערך של this
.
כשמפעילים פונקציה באמצעות השיטות call()
, bind()
או apply()
,
this
מפנה במפורש לאובייקט שנקרא:
let myFunction = function() {
console.log( this.myValue );
}
let myObject = {
"myValue" : "This is my string."
};
myFunction.call( myObject );
> "This is my string."
var myObject = {
myString: "This is my string.",
myMethod() {
console.log( this.myString );
}
};
setTimeout( myObject.myMethod.bind( myObject ), 100 );
> "This is my string."
קישור מפורש מבטל את הערך של this
שמסופק באמצעות קישור מרומז.
let myObject = {
"myValue" : "This string sits alongside myMethod.",
myMethod() {
console.log( this.myValue );
}
};
let myOtherObject = {
"myValue" : "This is a string in another object entirely.",
};
myObject.myMethod.call( myOtherObject );
> "This is a string in another object entirely."
אם קוראים לפונקציה בדרך שמגדירה את הערך של this
כ-
undefined
או null
, הערך הזה יוחלף ב-globalThis
מחוץ לערך מחמיר
מצב:
let myFunction = function() {
console.log( this );
}
myFunction.call( null );
> Window {...}
באופן דומה, אם קוראים לפונקציה באופן שתיתן ל-this
רכיב
הערך הזה יוחלף ב-
אובייקט wrapper של ערך פרימיטיבי
מחוץ למצב קפדני:
let myFunction = function() {
console.log( this );
}
let myNumber = 10;
myFunction.call( myNumber );
> Number { 10 }
במצב מחמיר, אי אפשר לאלץ בשום צורה את הערך של this
שמועבר לאובייקט,
גם אם הוא ערך ראשוני, null
או undefined
:
"use strict";
let myFunction = function() {
console.log( this );
}
let myNumber = 10;
myFunction.call( myNumber );
> 10
myFunction.call( null );
> null
קישור new
כש-class משמש כ-constructor באמצעות
מילת המפתח new
, this
מתייחסת למופע החדש שנוצר:
class MyClass {
myString;
constructor() {
this.myString = "My string.";
}
logThis() {
console.log( this );
}
}
const thisClass = new MyClass();
thisClass.logThis();
> Object { myString: "My string." }
באופן דומה, הערך של this
בתוך פונקציית constructor שנקראת באמצעות new
מתייחס לאובייקט שנוצר:
function MyFunction() {
this.myString = "My string.";
this.logThis = function() {
console.log( this );
}
}
const myObject = new MyFunction();
myObject.logThis();
> Object { myString: "My string.", logThis: logThis() }
קישור הגורם המטפל באירועים
בהקשר של גורמים מטפלים באירועים, הערך של this
מפנה לאובייקט
שמפעיל אותו. בתוך פונקציית הקריאה החוזרת של הגורם המטפל באירועים, פירוש הדבר הוא this
מפנה לרכיב המשויך ל-handler:
let button = document.querySelector( "button" );
button.addEventListener( "click", function( event ) { console.log( this ); } );
כשמשתמש יוצר אינטראקציה עם button
בקטע הקוד הקודם, התוצאה היא
אובייקט הרכיב שמכיל את <button>
עצמו:
> Button {}
כשפונקציית חץ משמשת כקריאה חוזרת (callback) של האזנה לאירועים, הערך של
הערך this
שוב מסופק באמצעות ההקשר הקרוב ביותר של הביצוע. למעלה
כלומר, הערך this
שבתוך פונקציית הקריאה החוזרת של הגורם המטפל באירועים הוא
globalThis
(או undefined
, במצב מחמיר):
let button = document.querySelector( "button" );
button.addEventListener( "click", ( event ) => { console.log( this ); } );
> undefined
כמו בכל אובייקט אחר, כשמשתמשים ב-call()
, ב-bind()
או ב-apply()
שיטות להפנות לפונקציית הקריאה החוזרת של האזנה לאירועים, this
מפנה לאובייקט באופן מפורש:
let button = document.querySelector( "button" );
let myObject = {
"myValue" : true
};
function handleClick() {
console.log( this );
}
button.addEventListener( "click", handleClick.bind( myObject ) );
> Object { myValue: true }
בדיקת ההבנה
בסקריפט שפועל בדפדפן אינטרנט, מהו האובייקט הגלובלי
שהמונח this
מתייחס אליו כשמשתמשים מחוץ לפונקציה, או
של האובייקט?
window
undefined
browser