การอ้างอิงถึง ECMA 5 จำเป็นต้องมีการชี้แจง
ฉันคิดว่ามันหมายถึง ECMA-262 Edition 5 ควรสังเกตว่า ECMA-262 (aka ECMAScript หรือ Javascript ที่ถูกต้องน้อยกว่า) เป็นภาษาสคริปต์ทั่วไปที่ถูกนำไปใช้ในอินเทอร์เน็ตเบราว์เซอร์ จากมาตรฐาน Edition 5.1:
ขั้นตอนต่อไปนี้จะดำเนินการเมื่อการควบคุมเข้าสู่บริบทการดำเนินการสำหรับโค้ดฟังก์ชันที่มีอยู่ในอ็อบเจ็กต์ฟังก์ชัน F ผู้เรียกจัดเตรียม thisArg และผู้เรียกให้ argumentsList:
- หากรหัสฟังก์ชันเป็นรหัสที่เข้มงวดให้ตั้งค่า ThisBinding เป็น thisArg
- ไม่เช่นนั้นหาก thisArg เป็นโมฆะหรือไม่ได้กำหนดให้ตั้งค่า ThisBinding เป็นวัตถุส่วนกลาง
- หาก Type (thisArg) ไม่ใช่ Object ให้ตั้งค่า ThisBinding เป็น ToObject (thisArg)
- อื่นตั้งค่า ThisBinding เป็น thisArg
- ... (ไม่เกี่ยวกับ "นี้")
คำว่า "global object" หมายถึงวัตถุใด ๆ ก็ตามที่อยู่บนสุดของห่วงโซ่ขอบเขต สำหรับเบราว์เซอร์สิ่งนี้จะเป็นอ็อบเจ็กต์ "หน้าต่าง" แต่นี่เป็นทางเลือกในการใช้งาน (โฮสต์สคริปต์ Windows มีอ็อบเจ็กต์ส่วนกลางที่มองไม่เห็น แต่ไม่มีโหมดที่เข้มงวดดังนั้นการอ้างอิงที่ไม่มีเงื่อนไขจึงเข้าถึงคุณสมบัติของมันและไม่มี "ตัวเอง" ทั่วโลก) นอกจากนี้ต้องเปิดใช้งาน "โหมดเข้มงวด" อย่างชัดเจนมิฉะนั้นจะไม่ทำงาน (มาตรา 14.1 ของมาตรฐาน) ด้วยเหตุนี้ "this" ที่ไม่ได้กำหนดจะยังคงแก้ไขให้กับวัตถุส่วนกลาง (หน้าต่าง) ใน "ECMA 5" ที่โหมดเข้มงวดไม่ทำงาน
ดังนั้นคำตอบสำหรับคำถามคือ:
"this" หมายถึงวัตถุที่เรียกใช้ฟังก์ชันเสมอ หากอ็อบเจ็กต์ไม่ได้เรียกใช้ฟังก์ชัน (เช่นไม่ใช่การเรียกใช้เมธอด) ดังนั้น "this" (ที่ส่งผ่านไปยังฟังก์ชัน) จะเป็น "ไม่ได้กำหนด" อย่างไรก็ตามหากไม่ใช้โหมดเข้มงวด "this" ที่ไม่ได้กำหนดจะถูกตั้งค่าเป็นวัตถุส่วนกลาง (กฎ 2 ด้านบน)
"ตัวเอง" ไม่มีความหมายทางวากยสัมพันธ์พิเศษเป็นเพียงตัวระบุ เบราว์เซอร์มักจะกำหนด window.self (เป็นเพียงคุณสมบัติของ global window object) = window ส่งผลให้มีการอ้างถึง "ตัวตน" อย่างไม่มีเงื่อนไขเหมือนกับ "หน้าต่าง" UNLESS "self" ได้รับการกำหนดใหม่ภายในขอบเขตที่ปิดล้อม (เช่น "var self = this;" ด้านบนขอให้โชคดีในการนิยาม "this" ใหม่)
ดังนั้นคำอธิบายทั้งหมดของตัวอย่างข้างต้นคือ:
outer func: this.foo = bar
// "this" refers to the invoking object "myObject"
outer func: self.foo = bar
// "self" resolves to the variable in the local scope which has been set to "this" so it is also "myObject"
inner func: this.foo = undefined
// "this" refers to the invoking object (none) and so is replaced by the global object (strict mode must be off). "window" has no foo property so its "value" is undefined.
inner func: self.foo = bar
// self resolves to the variable in the enclosing scope which is still "myObject"
รูปแบบที่น่าสนใจของตัวอย่างจะสร้างการปิดโดยส่งคืนการอ้างอิงไปยังฟังก์ชันภายใน
var myObject = {
foo: "bar",
func: function() {
var self = this;
console.log("outer func: this.foo = " + this.foo);
console.log("outer func: self.foo = " + self.foo);
return function() {
console.log("inner func: this.foo = " + this.foo);
console.log("inner func: self.foo = " + self.foo);
};
}
};
var yourObject = {
foo: "blat",
func: myObject.func() // function call not function object
};
console.log("----");
yourObject.func();
การผลิต
outer func: this.foo = bar
outer func: self.foo = bar
----
inner func: this.foo = blat
inner func: self.foo = bar
สังเกตว่าฟังก์ชันภายในไม่ได้ถูกเรียกใช้อย่างไรจนกว่า yourObject จะเรียกใช้ ดังนั้น this.foo จึงเป็น yourObject.foo แต่ตัวเองยังคงแก้ไขตัวแปรในขอบเขตการปิดล้อมซึ่งในขณะที่ส่งคืนวัตถุฟังก์ชันภายในคือ (และในการปิดผลลัพธ์ยังคงเป็น) myObject ดังนั้นภายในฟังก์ชันภายใน "สิ่งนี้" หมายถึงวัตถุที่เรียกฟังก์ชันภายในในขณะที่ "ตัวเอง" หมายถึงวัตถุที่เรียกฟังก์ชันด้านนอกเพื่อสร้างการอ้างอิงถึงฟังก์ชันภายใน
ในการสรุปเนื้อหาโดยสรุป "this" ถูกกำหนดโดยมาตรฐานภาษา "self" ถูกกำหนดโดยผู้ใดก็ตามที่กำหนด (runtimeplementer หรือ end programmer)