คีย์เวิร์ด this
หมายถึงค่าของออบเจ็กต์ที่เชื่อมโยงกับฟังก์ชัน ณ เวลาเรียกใช้ ซึ่งหมายความว่าค่าของคีย์เวิร์ดจะแตกต่างกันไปโดยขึ้นอยู่กับว่ามีการเรียกใช้ฟังก์ชันเป็นเมธอด เป็นฟังก์ชันสแตนด์อโลน หรือเป็นคอนสตรัคเตอร์
เมื่อมีการเรียกใช้ฟังก์ชัน ระบบจะสร้างอินสแตนซ์ของคีย์เวิร์ด 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
ภายในเมธอดนั้นจะอ้างอิงออบเจ็กต์ที่มีเมธอดนั้น ซึ่งจะให้สิทธิ์เข้าถึงเมธอดและพร็อพเพอร์ตี้ที่อยู่ข้างๆ ดังนี้
let myObject = {
myValue: "This is my string.",
myMethod() {
console.log( this.myValue );
}
};
myObject.myMethod();
> "This is my string."
ดูเหมือนว่าค่าของ this
จะขึ้นอยู่กับวิธีกำหนดฟังก์ชันและออบเจ็กต์ที่ล้อมรอบ แต่บริบทของค่า this
คือบริบทการเรียกใช้ปัจจุบัน ในกรณีนี้ บริบทการดําเนินการคือออบเจ็กต์ myObject
เรียกใช้เมธอด 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
เป็นออบเจ็กต์ที่ "เป็นเจ้าของ" เมธอดนั้น แต่ 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() }
การเชื่อมโยงที่ชัดเจน
การเชื่อมโยงโดยนัยจะจัดการ Use Case ส่วนใหญ่สำหรับการทำงานกับ this
อย่างไรก็ตาม บางครั้งคุณอาจต้องใช้ค่าของ this
เพื่อแสดงบริบทการเรียกใช้ที่เฉพาะเจาะจงแทนบริบทที่คาดคะเน ตัวอย่างที่แสดงให้เห็นถึงการทำงาน (อาจล้าสมัยไปหน่อย) คือการทำงานกับ this
ภายในฟังก์ชัน Callback ของ setTimeout
เนื่องจาก Callback นี้มีบริบทการเรียกใช้ที่ไม่ซ้ำกัน
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
ในฐานโค้ดเดิม รูปแบบตัวระบุทั่วไปเหล่านี้สําหรับตัวแปรที่มีค่า 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 เป็นคอนสตรัคเตอร์โดยใช้คีย์เวิร์ด 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
ภายในฟังก์ชันคอนสตรัคเตอร์ที่เรียกใช้โดยใช้ 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
จะอ้างอิงออบเจ็กต์ที่เรียกใช้ตัวแฮนเดิลนั้น ภายในฟังก์ชัน Callback ของตัวแฮนเดิลเหตุการณ์ this
จะอ้างอิงองค์ประกอบที่เชื่อมโยงกับตัวแฮนเดิล ดังนี้
let button = document.querySelector( "button" );
button.addEventListener( "click", function( event ) { console.log( this ); } );
เมื่อผู้ใช้โต้ตอบกับ button
ในข้อมูลโค้ดที่ติดทั่วเว็บไซต์ก่อนหน้า ผลลัพธ์ที่ได้คือออบเจ็กต์องค์ประกอบที่มี <button>
ดังนี้
> Button {}
เมื่อใช้ฟังก์ชันลูกศรเป็น Callback ของ Listener เหตุการณ์ บริบทการเรียกใช้ที่ใกล้เคียงที่สุดจะระบุค่าของ this
อีกครั้ง ที่ระดับบนสุด this
ภายในฟังก์ชัน Callback ของตัวแฮนเดิลเหตุการณ์จะมีลักษณะดังนี้globalThis
let button = document.querySelector( "button" );
button.addEventListener( "click", ( event ) => { console.log( this ); } );
> undefined
เช่นเดียวกับออบเจ็กต์อื่นๆ เมื่อคุณใช้เมธอด call()
, bind()
หรือ apply()
เพื่ออ้างอิงฟังก์ชัน Callback ของ Listener เหตุการณ์ 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