this และ Context
this คืออะไร?
หัวข้อที่มีชื่อว่า “this คืออะไร?”this เป็น keyword พิเศษที่อ้างถึง execution context — object ที่ถือเป็น receiver ของการเรียกฟังก์ชันปัจจุบัน ต่างจากภาษาส่วนใหญ่ this ใน JavaScript ไม่ถูก bind เมื่อนิยาม แต่ถูกกำหนด ณ เวลาที่เรียก โดยวิธีที่ฟังก์ชันถูก invoke
this ในรูปแบบการเรียกต่างๆ
หัวข้อที่มีชื่อว่า “this ในรูปแบบการเรียกต่างๆ”// 1. Method call — this คือ object ก่อนจุดconst user = { name: 'Alice', greet: function() { return 'Hi, I am ' + this.name; },};console.log(user.greet()); // 'Hi, I am Alice'
// 2. Plain function call — this คือ undefined (strict mode) หรือ globalThisfunction whoAmI() { return typeof this; // 'undefined' ใน strict mode}
// 3. Constructor call — this คือ object ที่สร้างใหม่function Person(name) { this.name = name;}const p = new Person('Bob');console.log(p.name); // 'Bob'การสูญเสีย this
หัวข้อที่มีชื่อว่า “การสูญเสีย this”ปัญหาที่พบบ่อยที่สุด: การแยก method ออกจาก object ทำให้ binding หาย
const timer = { label: 'tick', start: function() { // หลังจาก 0 ms fn ถูกเรียกเป็น plain function — this.label เป็น undefined setTimeout(function() { console.log(this.label); // undefined — 'this' ไม่ใช่ timer }, 0); },};call, apply และ bind
หัวข้อที่มีชื่อว่า “call, apply และ bind”ทั้งสาม method นี้ให้คุณ กำหนด this อย่างชัดเจน
function introduce(greeting, punctuation) { return greeting + ', I am ' + this.name + punctuation;}
const obj = { name: 'Carol' };
// call — ส่ง arguments แยกกันintroduce.call(obj, 'Hello', '!'); // 'Hello, I am Carol!'
// apply — ส่ง arguments เป็น arrayintroduce.apply(obj, ['Hey', '.']); // 'Hey, I am Carol.'
// bind — return ฟังก์ชันใหม่ที่ this ถูก bind อย่างถาวรconst boundIntroduce = introduce.bind(obj);boundIntroduce('Hi', '?'); // 'Hi, I am Carol?'Arrow functions และ this
หัวข้อที่มีชื่อว่า “Arrow functions และ this”Arrow functions ไม่มี this ของตัวเอง แต่ inherit this จาก lexical enclosing scope — function หรือ module scope รอบนอกที่จุดที่เขียน
const timer2 = { label: 'tick', start: function() { // Arrow function inherit 'this' จาก start() — ซึ่งคือ timer2 setTimeout(() => { console.log(this.label); // 'tick' — bound อย่างถูกต้อง }, 0); },};ทำให้ arrow functions เป็นตัวเลือกที่เหมาะสมสำหรับ callbacks ภายใน methods