Trong JavaScript, this
là một từ khóa đặc biệt, đại diện cho ngữ cảnh hiện tại của hàm hoặc đối tượng. Cụ thể, this
thường tham chiếu đến đối tượng mà hàm đang được gọi từ nó, nhưng giá trị của this
có thể thay đổi tùy thuộc vào cách hàm được gọi.
this
:Khi bạn gọi một phương thức trên một đối tượng, this
bên trong phương thức sẽ tham chiếu đến đối tượng đó.
const person = { name: 'Alice', greet: function() { console.log(this.name); // 'this' ở đây là đối tượng 'person' } }; person.greet(); // Kết quả: 'Alice'
Trong một hàm thông thường, this
tham chiếu đến global object (trong trình duyệt là đối tượng window
), nhưng trong chế độ strict mode ("use strict"
), this
sẽ là undefined
.
function showName() { console.log(this); // Trong trình duyệt, this sẽ là window } showName();
Khi bạn sử dụng hàm khởi tạo (constructor function
), this
sẽ tham chiếu đến đối tượng mới được tạo ra từ constructor đó.
function Car(brand) { this.brand = brand; } const myCar = new Car('Toyota'); console.log(myCar.brand); // 'Toyota'
Khi một sự kiện DOM được kích hoạt, this
thường tham chiếu đến phần tử mà sự kiện đó được gán.
const button = document.querySelector('button'); button.addEventListener('click', function() { console.log(this); // 'this' ở đây là phần tử 'button' });
Trong arrow function, this
không bị ràng buộc theo cách truyền thống mà nó kế thừa giá trị của this
từ phạm vi cha gần nhất của nó.
const person = { name: 'Alice', greet: function() { const innerGreet = () => { console.log(this.name); // 'this' kế thừa từ 'person' }; innerGreet(); } }; person.greet(); // Kết quả: 'Alice'
call
, apply
, và bind
Bạn có thể sử dụng các phương thức call
, apply
, và bind
để thiết lập rõ ràng giá trị của this
khi gọi một hàm.
call
cho phép bạn gọi một hàm với một đối tượng cụ thể làm giá trị của this
.function show() { console.log(this.name); } const obj = { name: 'Alice' }; show.call(obj); // Kết quả: 'Alice'
apply
cũng tương tự như call
, nhưng bạn truyền đối số dưới dạng mảng.function introduce(greeting) { console.log(greeting + ', my name is ' + this.name); } const obj = { name: 'Alice' }; introduce.apply(obj, ['Hello']); // Kết quả: 'Hello, my name is Alice'
bind
tạo ra một hàm mới với this
được thiết lập.function show() { console.log(this.name); } const obj = { name: 'Alice' }; const boundShow = show.bind(obj); boundShow(); // Kết quả: 'Alice'
Trong JavaScript ES6, khi bạn sử dụng lớp (class), this
cũng tham chiếu đến đối tượng của lớp.
class Person { constructor(name) { this.name = name; } greet() { console.log(this.name); } } const alice = new Person('Alice'); alice.greet(); // Kết quả: 'Alice'
Trong các hàm xử lý Promise
, giá trị của this
cũng có thể không như mong đợi.
const obj = { name: 'Alice', greet: function() { return new Promise((resolve) => { resolve(this.name); // 'this' không được kế thừa từ obj }); } }; obj.greet().then((name) => console.log(name)); // Kết quả: 'Alice' trong bối cảnh đúng
this
Mặc dù this
là một phần quan trọng trong JavaScript, nhưng có một số lưu ý mà bạn cần ghi nhớ để tránh những vấn đề tiềm ẩn trong quá trình phát triển:
this
trong callbackKhi bạn truyền một hàm như là một callback, giá trị của this
có thể không phải là bạn mong đợi. Để khắc phục, bạn có thể sử dụng phương pháp bind
, hoặc sử dụng arrow functions để giữ nguyên ngữ cảnh.
const obj = { name: 'Alice', greet: function() { setTimeout(function() { console.log(this.name); // 'this' ở đây không phải là 'obj' }, 1000); } }; obj.greet(); // Kết quả: undefined // Sửa bằng cách sử dụng bind const objWithBind = { name: 'Alice', greet: function() { setTimeout(function() { console.log(this.name); }.bind(this), 1000); // Sử dụng bind để giữ giá trị của 'this' } }; objWithBind.greet(); // Kết quả: 'Alice' // Hoặc dùng arrow function const objWithArrow = { name: 'Alice', greet: function() { setTimeout(() => { console.log(this.name); // 'this' ở đây là 'objWithArrow' }, 1000); } }; objWithArrow.greet(); // Kết quả: 'Alice'
Khi sử dụng strict mode trong JavaScript ("use strict"
), this
trong hàm sẽ trở thành undefined
nếu không có ngữ cảnh. Điều này có thể giúp bạn phát hiện lỗi.
"use strict"; function show() { console.log(this); // Kết quả: undefined } show();
Khi bạn gọi một phương thức từ một đối tượng, this
sẽ tham chiếu đến đối tượng đó. Nhưng khi bạn gọi một hàm thông thường, this
sẽ là đối tượng toàn cầu (trong trình duyệt là window
), điều này có thể gây nhầm lẫn nếu không hiểu rõ.
Khi gọi một hàm mà không có ngữ cảnh, this
sẽ trỏ đến đối tượng toàn cầu, vì vậy hãy cẩn thận khi bạn cần sử dụng this
trong các hàm.
function globalFunc() { console.log(this); // Trỏ đến window trong trình duyệt } globalFunc();
Hãy cố gắng tổ chức mã của bạn sao cho giá trị của this
luôn rõ ràng. Sử dụng các phương thức như bind
, call
, hoặc apply
một cách hợp lý để thiết lập giá trị cho this
và tránh sự nhầm lẫn trong quá trình phát triển.
console.log(this)
Đôi khi, cách tốt nhất để hiểu cách hoạt động của this
là thử nghiệm và xem kết quả bằng cách sử dụng console.log(this)
trong các ngữ cảnh khác nhau.
function checkThis() { console.log(this); } const obj1 = { name: 'Alice', method: checkThis }; const obj2 = { name: 'Bob' }; obj1.method(); // 'this' là obj1 checkThis(); // 'this' là window (trong trình duyệt) checkThis.call(obj2); // 'this' là obj2
Hiểu cách hoạt động của this
trong JavaScript là rất quan trọng để xây dựng ứng dụng hiệu quả. Bằng cách nắm rõ các quy tắc và lưu ý về this
, bạn có thể tránh được nhiều lỗi phổ biến và làm cho mã của mình dễ bảo trì và mở rộng hơn. Hãy thực hành thường xuyên và thử nghiệm trong các tình huống khác nhau để làm quen với hành vi của this
.