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?
window
browser
undefined