ทำความเข้าใจว่า this ถูกกำหนดค่าแบบไดนามิกอย่างไร โปรโตไทป์เชนทำงานอย่างไร และคลาสเพิ่มอะไรเข้าไปในโมเดลของอ็อบเจกต์กันแน่
เปิดบทเรียนนี้ใน Kodokonค่าของ this ถูกตัดสิน ณ จุดที่เรียกใช้ ไม่ใช่ตอนประกาศ มีสี่กฎ เรียงตามลำดับความสำคัญจากมากไปน้อย: การเรียกด้วย new, การผูกอย่างชัดเจน (call, apply, bind), การเรียกในฐานะเมทอด (obj.fn()) และการเรียกแบบธรรมดา (fn()) ซึ่งให้ค่า undefined ในโหมด strict บั๊กที่พบบ่อยที่สุดในโลกจริงตามมาโดยตรง: การดึงเมทอดออกจากอ็อบเจกต์ของมันทำให้การผูกโดยปริยายพัง
const user = {
name: "Ada",
greet() {
return "Hello, " + this.name;
},
};
console.log(user.greet()); // "Hello, Ada"
const detached = user.greet;
// detached(); // TypeError: this is undefined
const bound = user.greet.bind(user);
console.log(bound()); // "Hello, Ada"arrow function ไม่มี this เป็นของตัวเอง: มันจับ this แบบ เล็กซิคัล จากขอบเขตที่ครอบมันไว้ เหมือนกับ closure ทำให้มันเหมาะกับคอลแบ็ก แต่กลับให้ผลตรงข้ามเมื่อใช้เป็นเมทอดใน object literal ซึ่ง this จะชี้ไปยังขอบเขตภายนอก เบื้องหลังนั้น อ็อบเจกต์ทุกตัวมอบหมายผ่าน โปรโตไทป์เชน: พร็อพเพอร์ตีที่หายไปจะถูกค้นหาทีละลิงก์จนกว่าจะถึง null
function Animal(name) {
this.name = name;
}
Animal.prototype.describe = function () {
return this.name + " is an animal";
};
const dog = new Animal("Rex");
console.log(dog.describe()); // "Rex is an animal"
console.log(Object.getPrototypeOf(dog) ===
Animal.prototype); // true
console.log(dog.hasOwnProperty("describe")); // falseไวยากรณ์ class ไม่ได้เปลี่ยนโมเดลนี้: มันทำให้อ่านง่ายขึ้น เมทอดที่ประกาศในตัวคลาสจะไปอยู่บน Constructor.prototype และจึงถูก ใช้ร่วมกัน ส่วนฟิลด์ของอินสแตนซ์ (รวมถึง arrow function ที่กำหนดเป็นฟิลด์) จะถูกสร้างใหม่ ต่อหนึ่งอินสแตนซ์: รับประกันการผูก this แต่ต้นทุนหน่วยความจำเพิ่มทวีคูณ สุดท้าย ฟิลด์ #private ให้ความเป็นส่วนตัวที่บังคับโดยเอนจิน ต่างจากธรรมเนียม _underscore
class BankAccount {
#balance = 0;
deposit(amount) {
if (amount <= 0) throw new Error("Invalid amount");
this.#balance += amount;
return this;
}
get balance() {
return this.#balance;
}
}
const account = new BankAccount();
account.deposit(50).deposit(25);
console.log(account.balance); // 75this มีค่าอะไรระหว่างการเรียกแบบธรรมดา fn() ที่ไม่มีอ็อบเจกต์และไม่มีการผูกอย่างชัดเจน?this?