คีย์เวิร์ดนี้

คีย์เวิร์ด 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 (หรือ undefined ในโหมดเข้มงวด):

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