Từ khóa này

Từ khoá this đề cập đến giá trị của đối tượng liên kết với vào thời điểm gọi, tức là giá trị của hàm sẽ khác nhau về việc một hàm được gọi dưới dạng phương thức, hàm độc lập hay hàm khởi tạo.

Khi được gọi, một hàm sẽ tạo một thực thể của từ khoá this các cảnh dưới dạng tham chiếu đến đối tượng chứa hàm đó, cung cấp cho quyền truy cập vào các thuộc tính và phương thức được xác định cùng với nó trong phạm vi của nó. Cách làm việc với this cũng tương tự như cách làm việc với một biến được khai báo cùng với const. Giống như một hằng số, bạn không thể xoá this và không thể lấy giá trị của nó đã chỉ định lại, nhưng các phương thức và thuộc tính của đối tượng mà từ khoá this chứa có thể thay đổi được.

Liên kết toàn cục

Bên ngoài một hàm hoặc ngữ cảnh của một đối tượng, this đề cập đến Thuộc tính globalThis là tham chiếu đến đối tượng toàn cục trong hầu hết Môi trường JavaScript. Trong bối cảnh tập lệnh đang chạy trên trình duyệt web, đối tượng toàn cục là đối tượng window:

this;
> Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, ...}

Trong Node.js, globalThis là đối tượng global:

$ node
Welcome to Node.js v20.10.0.
Type ".help" for more information.
> this
<ref *1> Object [global] {
...
}

Ngoài chế độ nghiêm ngặt, this cũng tham chiếu đến đối tượng chung bên trong một đối tượng độc lập vì Window mẹ là đối tượng "sở hữu" hiệu quả các hàm đó.

function myFunction() {
    console.log( this );
}
myFunction();
> Window {...}

(function() {
    console.log( this );
}());
> Window {...}

Khi sử dụng chế độ nghiêm ngặt, this có giá trị undefined bên trong một giá trị độc lập hàm:

(function() {
    "use strict";
    console.log( this );
}());
> undefined

Trước khi chế độ nghiêm ngặt ra mắt, giá trị null hoặc undefined cho this sẽ được thay thế bằng một tham chiếu đến đối tượng toàn cục. Đôi khi, bạn có thể thấy liên kết chung còn được gọi là "liên kết mặc định" do hành vi cũ này.

Liên kết ngầm ẩn

Khi một hàm được gọi dưới dạng phương thức của một đối tượng, một thực thể của this bên trong phương thức đó tham chiếu đến đối tượng chứa phương thức, cấp quyền truy cập vào các phương thức và thuộc tính tương ứng:

let myObject = {
    myValue: "This is my string.",
    myMethod() {
            console.log( this.myValue );
    }
};

myObject.myMethod();
> "This is my string."

Có thể giá trị của this phụ thuộc vào cách hàm và đã xác định đối tượng bao quanh. Thay vào đó, ngữ cảnh cho giá trị của this là ngữ cảnh thực thi hiện tại. Trong trường hợp này, ngữ cảnh thực thi là Đối tượng myObject đang gọi phương thức myMethod, vì vậy myObject là giá trị với giá this. Đây có vẻ là tính kỹ thuật trong bối cảnh trước đó ví dụ, nhưng để sử dụng this nâng cao hơn, đây là một điểm khác biệt cần thiết đối với của chúng tôi.

Nhìn chung, hãy sử dụng this theo cách không mong muốn mã xung quanh sẽ có bất kỳ cấu trúc cụ thể nào. Trường hợp ngoại lệ của quy tắc này là ES5 Các hàm mũi tên.

this trong hàm mũi tên

Trong hàm mũi tên, this phân giải thành một liên kết trong một môi trường đính kèm từ vựng. Điều này có nghĩa là this trong hàm mũi tên tham chiếu đến giá trị của this trong hàm đó ngữ cảnh kèm theo gần nhất:

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 {...}

Trong ví dụ trước, myObject.myMethod() ghi lại myObject làm đối tượng "sở hữu" phương thức đó, nhưng myObject.myArrowFunction() trả về globalThis (hoặc undefined), vì thực thể của this bên trong hàm mũi tên thay vào đó chuyển sang phạm vi bao quanh cao nhất.

Trong ví dụ sau, myEnclosingMethod tạo một hàm mũi tên trên chứa đối tượng đó khi được thực thi. Thực thể của this bên trong hàm mũi tên hiện tham chiếu đến giá trị của this bên trong phần bao quanh môi trường, là phương thức chứa hàm mũi tên đó. Vì giá trị của this bên trong myEnclosingMethod tham chiếu đến myObject, sau khi bạn định nghĩa hàm mũi tên, this bên trong hàm mũi tên cũng tham chiếu đến myObject:

let myObject = {
    myMethod() { console.log( this ); },
    myEnclosingMethod: function () {
        this.myArrowFunction = () => { console.log(this) };
    }
};

myObject.myEnclosingMethod();
myObject.myArrowFunction();
> Object { myMethod: myMethod(), myArrowFunction: myArrowFunction() }

Liên kết tường minh

Liên kết ngầm ẩn xử lý hầu hết các trường hợp sử dụng để làm việc với this. Tuy nhiên, bạn đôi khi có thể cần giá trị của this để thể hiện một quá trình thực thi cụ thể ngữ cảnh, thay vì ngữ cảnh giả định. Hình minh hoạ, nếu đã lỗi thời, ví dụ là làm việc với this trong hàm callback của setTimeout, vì lệnh gọi lại này có ngữ cảnh thực thi duy nhất:

var myObject = {
  myString: "This is my string.",
  myMethod() {
    console.log( this.myString );
  }
};
myObject.myMethod();
> "This is my string."

setTimeout( myObject.myMethod, 100 );
> undefined

Mặc dù thiếu sót cụ thể này của setTimeout đã được giải quyết bằng các tính năng khác, các vấn đề tương tự về "thua cuộc" this đã được xử lý trước đó bằng cách tạo một tham chiếu rõ ràng đến giá trị của this trong phạm vi của ngữ cảnh dự định. Đôi khi, bạn có thể thấy các trường hợp this được chỉ định cho một biến sử dụng các giá trị nhận dạng như that, self hoặc _this theo phương thức cũ cơ sở mã. Đây là những quy ước nhận dạng phổ biến cho các biến chứa đã truyền giá trị this.

Khi bạn gọi một hàm bằng phương thức call(), bind() hoặc apply(), this tham chiếu rõ ràng đến đối tượng đang được gọi:

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."

Liên kết tường minh sẽ ghi đè giá trị this do liên kết ngầm ẩn cung cấp.

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."

Nếu một hàm được gọi theo cách đặt giá trị của this thành undefined hoặc null, giá trị đó sẽ được thay thế bằng globalThis bên ngoài quy tắc nghiêm ngặt chế độ:

let myFunction = function() {
    console.log( this );
}

myFunction.call( null );
> Window {...}

Tương tự, nếu một hàm được gọi theo cách sẽ cung cấp cho this một dữ liệu nguyên thuỷ thì giá trị đó sẽ được thay bằng đối tượng trình bao bọc của giá trị gốc ngoài chế độ nghiêm ngặt:

let myFunction = function() {
    console.log( this );
}

let myNumber = 10;

myFunction.call( myNumber );
> Number { 10 }

Ở chế độ nghiêm ngặt, giá trị this đã truyền không bị ép buộc thành đối tượng theo bất kỳ cách nào, ngay cả khi đó là giá trị gốc, giá trị null hoặc undefined:

"use strict";
let myFunction = function() {
    console.log( this );
}

let myNumber = 10;

myFunction.call( myNumber );
> 10

myFunction.call( null );
> null

Liên kết new

Khi một lớp được dùng làm hàm khởi tạo bằng cách sử dụng Từ khoá new, this đề cập đến phiên bản mới tạo:

class MyClass {
    myString;
    constructor() {
        this.myString = "My string.";
    }
    logThis() {
        console.log( this );
    }
}
const thisClass = new MyClass();

thisClass.logThis();
> Object { myString: "My string." }

Tương tự, giá trị của this bên trong hàm hàm khởi tạo được gọi bằng new đề cập đến đối tượng đang được tạo:

function MyFunction() {
  this.myString = "My string.";
  this.logThis = function() {
    console.log( this );
  }
}
const myObject = new MyFunction();

myObject.logThis();
> Object { myString: "My string.", logThis: logThis() }

Liên kết trình xử lý sự kiện

Trong ngữ cảnh trình xử lý sự kiện, giá trị của this tham chiếu đến đối tượng gọi nó. Bên trong hàm callback của một trình xử lý sự kiện, điều đó có nghĩa là this tham chiếu đến phần tử liên kết với trình xử lý:

let button = document.querySelector( "button" );

button.addEventListener( "click", function( event ) { console.log( this ); } );

Khi người dùng tương tác với button trong đoạn mã trước đó, kết quả sẽ là đối tượng phần tử chứa chính <button>:

> Button {}

Khi dùng hàm mũi tên làm lệnh gọi lại trình nghe sự kiện, giá trị của this một lần nữa được cung cấp bởi ngữ cảnh thực thi gần nhất. Phía trên cùng điều đó nghĩa là this bên trong hàm callback của trình xử lý sự kiện globalThis (hoặc undefined, ở chế độ nghiêm ngặt):

let button = document.querySelector( "button" );

button.addEventListener( "click", ( event ) => { console.log( this ); } );
> undefined

Giống như mọi đối tượng khác, khi bạn sử dụng call(), bind() hoặc apply() để tham chiếu hàm callback của một trình nghe sự kiện, this tham chiếu rõ ràng đến đối tượng:

let button = document.querySelector( "button" );
let myObject = {
    "myValue" : true
};
function handleClick() {
    console.log( this );
}

button.addEventListener( "click", handleClick.bind( myObject ) );
> Object { myValue: true }

Kiểm tra kiến thức

Đối với tập lệnh chạy trong trình duyệt web, đối tượng toàn cục là gì mà this tham chiếu đến khi được sử dụng bên ngoài một hàm hoặc ngữ cảnh của một đối tượng?

Đối tượng window
Đối tượng browser
Đối tượng undefined