מילת המפתח הזו

מילת המפתח 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
האובייקט browser
האובייקט undefined