1. מה זה Context (הקשר)?
Context (הקשר) בפונקציות ב-JavaScript מתייחס לערך של המילה השמורה this
בתוך הפונקציה. הקשר קובע על איזה אובייקט פונקציה מופעלת ומי המאפיינים שהיא תוכל לגשת אליהם. ערך this
תלוי בצורה שבה הפונקציה נקראת, ולא איפה היא הוגדרה.
2. הבנה בסיסית של this
ב-JavaScript, המילה השמורה this
מתייחסת לאובייקט שבו הפונקציה פועלת כרגע. הקשר של this
משתנה בהתאם לאיך הפונקציה נקראת.
דוגמה בסיסית:
const person = {
name: "Alice",
greet: function() {
console.log("Hello, my name is " + this.name);
}
};
person.greet(); // מציג "Hello, my name is Alice"
הסבר:
- בתוך הפונקציה
greet
, המילהthis
מתייחסת לאובייקטperson
. - כאשר קוראים לפונקציה באמצעות
person.greet()
,this
מצביע על האובייקטperson
, ולכן הפלט הוא "Hello, my name is Alice".
3. this
בקונטקסט גלובלי
כאשר משתמשים ב-this
מחוץ לפונקציה או בתוך פונקציה גלובלית (שאינה שייכת לאובייקט), this
מתייחס לאובייקט הגלובלי (ב-דפדפן זה יהיה window
).
דוגמה:
console.log(this); // בדפדפן זה יציג את האובייקט הגלובלי window
דוגמה בתוך פונקציה גלובלית:
function showThis() {
console.log(this);
}
showThis(); // מציג את אובייקט window
הסבר:
- כאשר לא מוגדר אובייקט ספציפי שבו הפונקציה מופעלת,
this
מתייחס לאובייקט הגלובלי (window
בדפדפן אוglobal
ב-Node.js).
4. this
באובייקטים
כאשר פונקציה מוגדרת כחלק מאובייקט (שיטה בתוך אובייקט), this
מתייחס לאובייקט שבו הפונקציה מופעלת.
דוגמה:
const car = {
brand: "Toyota",
model: "Corolla",
displayInfo: function() {
console.log("Car: " + this.brand + " " + this.model);
}
};
car.displayInfo(); // מציג "Car: Toyota Corolla"
הסבר:
- הפונקציה
displayInfo
נמצאת בתוך האובייקטcar
, ולכן כאשר היא נקראת באמצעותcar.displayInfo()
, המילהthis
מתייחסת לאובייקטcar
.
5. this
בתוך פונקציות חץ (Arrow Functions)
פונקציות חץ (Arrow Functions) מתנהגות בצורה שונה עם this
. בפונקציות חץ, this
נשאר זהה להקשר שבו הפונקציה נכתבה ולא משתנה לפי אופן הקריאה לפונקציה.
דוגמה:
const person = {
name: "Bob",
greet: function() {
const innerGreet = () => {
console.log("Hello, my name is " + this.name);
};
innerGreet();
}
};
person.greet(); // מציג "Hello, my name is Bob"
הסבר:
- הפונקציה
innerGreet
היא פונקציית חץ, ולכןthis
בתוכה נשאר מתייחס לאותו אובייקט שבו היא נכתבה, שהואperson
במקרה הזה. - גם בתוך
innerGreet
,this.name
מתייחס ל-person.name
ומחזיר את השם "Bob".
דוגמה לפונקציה רגילה:
const person = {
name: "Bob",
greet: function() {
function innerGreet() {
console.log("Hello, my name is " + this.name);
}
innerGreet();
}
};
person.greet(); // מציג "Hello, my name is undefined"
הסבר:
- כאשר משתמשים בפונקציה רגילה בתוך פונקציה אחרת,
this
מתעדכן להקשר חדש (במקרה זה, האובייקט הגלובלי), ולכןthis.name
מחזירundefined
.
6. שימוש ב-bind
, call
, ו-apply
לשינוי הקשר
ניתן לשנות את ערך this
באופן ידני באמצעות שלוש פונקציות עזר: bind
, call
, ו-apply
.
bind
: קובע הקשר קבוע
bind
יוצר גרסה חדשה של הפונקציה שבה this
נקבע לערך מסוים, אך לא קורא לפונקציה מיד.
דוגמה:
const person = {
name: "Alice",
};
function greet() {
console.log("Hello, my name is " + this.name);
}
const greetPerson = greet.bind(person);
greetPerson(); // מציג "Hello, my name is Alice"
הסבר:
- הפונקציה
greet.bind(person)
יוצרת פונקציה חדשה שבהthis
קבוע ומפנה ל-person
. - כאשר קוראים ל-
greetPerson()
, הפונקציה מדפיסה את השם שלperson
.
call
: מפעיל את הפונקציה עם הקשר חדש
call
מפעיל את הפונקציה באופן מיידי ומאפשר להעביר לה ערך של this
וכן פרמטרים.
דוגמה:
const person = {
name: "Bob",
};
function greet(greeting) {
console.log(greeting + ", my name is " + this.name);
}
greet.call(person, "Hi"); // מציג "Hi, my name is Bob"
הסבר:
call
מאפשר להפעיל את הפונקציהgreet
עם הקשר שבוthis
מצביע על האובייקטperson
ולשלוח את הפרמטרים לפונקציה.
apply
: כמו call
, אך עם מערך פרמטרים
apply
דומה מאוד ל-call
, אבל במקום להעביר פרמטרים אחד אחד, היא מקבלת מערך של פרמטרים.
דוגמה:
const person = {
name: "Charlie",
};
function greet(greeting, punctuation) {
console.log(greeting + ", my name is " + this.name + punctuation);
}
greet.apply(person, ["Hello", "!"]); // מציג "Hello, my name is Charlie!"
הסבר:
apply
מפעילה את הפונקציה עם אותו הקשר כמוcall
, אבל מעבירה את הפרמטרים בתוך מערך.
7. דוגמה מלאה: שינוי הקשר עם פונקציות עזר
נבנה דוגמה שמשתמשת ב-bind
, call
, ו-apply
כדי לשנות את ההקשר של הפונקציה.
const user1 = {
name: "Alice",
};
const user2 = {
name: "Bob",
};
function greet(greeting) {
console.log(greeting + ", my name is " + this.name);
}
// שימוש ב-bind כדי ליצור פונקציה חדשה עם הקשר ל-user1
const greetAlice = greet.bind(user1);
greetAlice("Hello"); // מציג "Hello, my name is Alice"
// שימוש ב-call כדי להפעיל את הפונקציה עם הקשר ל-user2
greet.call(user2, "Hi"); // מציג "Hi, my name is Bob"
// שימוש ב-apply כדי להפעיל את הפונקציה עם הקשר ל-user1 ולשלוח פרמטרים כמערך
greet.apply(user1, ["Hey"]); // מציג "Hey, my name is Alice"
הסבר:
- בעזרת
bind
יצרנו פונקציה חדשה שההקשר שלה הואuser1
. - עם
call
, הפעלנו את הפונקציה עם הקשר שונה (user2
). - עם
apply
, השתמשנו במערך פרמטרים להעברת נתונים לפונקציה.
8. סיכום ההבדלים בין פונקציות רגילות ל-Arrow Functions
- פונקציות רגילות: ערך
this
משתנה בהתאם לאופן הקריאה לפונקציה. ניתן לשנות אותו עםbind
,call
, ו-apply
. - פונקציות חץ (Arrow Functions): ערך
this
נלקח מההקשר שבו הפונקציה נכתבה, והוא לא משתנה בעת הקריאה לפונקציה.
סיכום
בפרק זה למדנו על:
- מהו ההקשר (
this
) בפונקציות ב-JavaScript ואיך הוא משתנה בהתאם לצורת הקריאה לפונקציה. - ההבדלים בין
this
בפונקציות רגילות לביןthis
בפונקציות חץ. - שימוש ב-
bind
,call
, ו-apply
לשינוי הקשר הפונקציה באופן ידני. - דוגמאות שונות לשימוש בהקשר הפונקציה בסביבות שונות כמו אובייקטים, פונקציות גלובליות ופונקציות חץ.
בפרק הבא נעמיק בנושא Inheritance (ירושה) ונראה כיצד להרחיב מחלקות וירושה בין מחלקות ב-JavaScript.