ב- JavaScript, לכל פונקציה יש this
הפניה שנוצרת אוטומטית כשאתה מצהיר עליה.
JavaScript this
דומה למדי this
להתייחסות בשפות מבוססות מחלקה אחרות כגון Java או C # (JavaScript הוא שפה מבוססת אב-טיפוס וללא מושג "מחלקה"): הוא מצביע על האובייקט הקורא לפונקציה (אובייקט זה נקרא לפעמים כמו הקשר ). ב- JavaScript, אולם, ההפניה בתוך פונקציות יכולה להיות מחויבת לאובייקטים שונים בהתאם למקום שבו הפונקציה נקראת .this
להלן 5 כללים בסיסיים this
לכריכה ב- JavaScript:
חוק מספר 1
כאשר פונקציה נקראת בהיקף הגלובלי, this
ההפניה כברירת מחדל קשורה לאובייקט הגלובלי ( window
בדפדפן, או global
ב- Node.js). לדוגמה:
function foo() { this.a = 2; } foo(); console.log(a); // 2
הערה: אם אתה מצהיר על foo()
הפונקציה לעיל במצב קפדני, אז אתה קורא לפונקציה זו בהיקף גלובלי, this
יהיה undefined
וההקצאה this.a = 2
תזרוק Uncaught TypeError
חריג.
כלל 2
בואו נבחן דוגמה למטה:
function foo() { this.a = 2; } const obj = { foo: foo }; obj.foo(); console.log(obj.a); // 2
ברור שבקטע הקוד שלמעלה, foo()
הפונקציה נקראת עם הקשר היא obj
אובייקט this
וההתייחסות כעת קשורה ל obj
. לכן כאשר נקראת לפונקציה עם אובייקט הקשר, this
ההפניה תהיה קשורה לאובייקט זה.
כלל 3
.call
, .apply
ו .bind
יכול לשמש כל באתר הקריאה לאגד במפורש this
. השימוש .bind(this)
הוא משהו שאתה עשוי לראות בהרבה מאוד רכיבי תגובה.
const foo = function() { console.log(this.bar) } foo.call({ bar: 1 }) // 1
הנה דוגמה מהירה לאופן שבו כל אחד משמש לקישור this
:
.call()
:fn.call(thisObj, fnParam1, fnParam2)
.apply()
:fn.apply(thisObj, [fnParam1, fnParam2])
.bind()
:const newFn = fn.bind(thisObj, fnParam1, fnParam2)
כלל 4
function Point2D(x, y) { this.x = x; this.y = y; } const p1 = new Point2D(1, 2); console.log(p1.x); // 1 console.log(p1.y); // 2
הדבר שאתה חייב לשים לב אליו הוא Point2D
הפונקציה שנקראת עם new
מילת מפתח, this
וההתייחסות חייבת להיות p1
אובייקט. לכן כאשר נקראת לפונקציה עם new
מילת מפתח, היא תיצור אובייקט חדש this
וההתייחסות תהיה קשורה לאובייקט זה.
הערה: כשאתה קורא לפונקציה עם new
מילת מפתח, אנו מכנים אותה גם כפונקציית קונסטרוקטור .
כלל 5
JavaScript קובע את הערך this
בזמן הריצה, בהתבסס על ההקשר הנוכחי. אז this
יכול לפעמים להצביע על משהו אחר ממה שאתה מצפה.
שקול דוגמה זו של כיתת חתול בשיטה שנקראת makeSound()
, בעקבות הדפוס הכלל 4 (לעיל) עם פונקציית קונסטרוקטור new
ומילת המפתח.
const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.makeSound(); // Fat Daddy says: Mrrooowww
עכשיו בואו ננסה לתת לחתול דרך annoy()
לאנשים על ידי חזרה על הצליל שלו 100 פעמים, אחת לחצי שנייה.
const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; this.annoy = function() { let count = 0, max = 100; const t = setInterval(function() { this.makeSound(); // <-- this line fails with `this.makeSound is not a function` count++; if (count === max) { clearTimeout(t); } }, 500); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.annoy();
זה לא עובד מכיוון שבתוך setInterval
השיחה החוזרת יצרנו הקשר חדש עם היקף גלובלי, ולכן this
כבר לא מצביע על מופע החתול שלנו. בדפדפן אינטרנט, this
במקום זאת יצביע על אובייקט Window, שאין לו makeSound()
שיטה.
כמה דרכים לגרום לזה לעבוד:
- לפני שתיצור את ההקשר החדש, הקצה
this
למשתנה מקומי בשםme
, אוself
, או איך שלא תרצה לקרוא לו, והשתמש במשתנה זה בתוך החזרה להתקשרות.
const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; this.annoy = function() { let count = 0, max = 100; const self = this; const t = setInterval(function() { self.makeSound(); count++; if (count === max) { clearTimeout(t); } }, 500); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.annoy();
- עם ES6 תוכלו להימנע מהקצאה
this
למשתנה מקומי באמצעות פונקציית חץ, הנקשרתthis
להקשר של הקוד שמסביב במקום בו הוא מוגדר.
const Cat = function(name, sound) { this.name = name; this.sound = sound; this.makeSound = function() { console.log( this.name + ' says: ' + this.sound ); }; this.annoy = function() { let count = 0, max = 100; const t = setInterval(() => { this.makeSound(); count++; if (count === max) { clearTimeout(t); } }, 500); }; } const kitty = new Cat('Fat Daddy', 'Mrrooowww'); kitty.annoy();