Explore all courses in this category.
Explore all courses in this category.
Nguyễn Đình Cường
0 comment
09 Nov, 2026
this là một trong những thứ khiến người học JavaScript đau đầu nhất, vì giá trị của nó không cố định mà phụ thuộc vào cách hàm được gọi, chứ không phải nơi hàm được viết. Khi nắm được vài quy tắc, bạn sẽ đoán đúng this trong hầu hết tình huống.
Với hàm thường, hãy nhìn xem hàm được gọi như thế nào:
doiTuong.ham(): this là doiTuong (phần trước dấu chấm).ham(): this là undefined ở strict mode (module và class luôn là strict), hoặc đối tượng toàn cục ở chế độ lỏng.new: this là đối tượng mới được tạo.this là giá trị bạn chỉ định.const nguoi = {
ten: 'Lan',
chao() {
console.log('Xin chào, tôi là ' + this.ten);
},
};
nguoi.chao(); // 'Xin chào, tôi là Lan'
const f = nguoi.chao;
f(); // this không còn là nguoi, this.ten lỗi hoặc undefinedDòng cuối là lỗi kinh điển: tách phương thức ra khỏi đối tượng làm mất ngữ cảnh. Điều này hay xảy ra khi truyền phương thức làm callback, ví dụ button.addEventListener('click', nguoi.chao).
const chaoLan = nguoi.chao.bind(nguoi);
chaoLan(); // luôn đúng
function gioiThieu(loi) {
console.log(loi + ', ' + this.ten);
}
gioiThieu.call({ ten: 'Nam' }, 'Chào'); // truyền đối số lần lượt
gioiThieu.apply({ ten: 'Mai' }, ['Chào']); // truyền đối số bằng mảngbind trả về hàm mới với this đã khóa, còn call và apply gọi ngay lập tức. Cách ghi nhớ: apply dùng mảng, call dùng danh sách.
Arrow function không có this riêng. Nó dùng this của nơi nó được viết (lexical this). Điều này giải quyết nhiều rắc rối trong callback:
const dongHo = {
giay: 0,
chay() {
setInterval(() => {
this.giay++; // this là dongHo nhờ arrow function
console.log(this.giay);
}, 1000);
},
};
dongHo.chay();Nếu thay arrow function bằng function () {} thường trong setInterval, this sẽ không còn là dongHo. Ngược lại, đừng dùng arrow function làm phương thức của object khi bạn cần this trỏ về chính object:
const sai = {
ten: 'Lan',
chao: () => console.log(this.ten), // this không phải sai
};class NutDem {
constructor() {
this.dem = 0;
this.tang = this.tang.bind(this); // cố định this
}
tang() {
this.dem++;
}
}
// hoặc dùng trường class với arrow function
class NutDem2 {
dem = 0;
tang = () => {
this.dem++;
};
}Hai cách trên đều đảm bảo phương thức tang luôn gắn với đúng đối tượng, kể cả khi bạn truyền nó làm callback cho sự kiện. Trong React với class component, đây từng là điều bạn phải làm thường xuyên.
Với hàm thường dùng làm trình xử lý sự kiện, this là phần tử đã gắn trình lắng nghe (event.currentTarget). Với arrow function thì không. Vì sự khác biệt dễ gây nhầm, nhiều người chọn dùng event.currentTarget trực tiếp thay vì this.
this, đừng dùng nó. Hàm thuần dễ kiểm thử hơn.console.log(this) để xem ngữ cảnh.this rơi vào đối tượng toàn cục.Hãy thử đoán đoạn này in ra gì:
const obj = {
ten: 'A',
a() { return this.ten; },
b: () => typeof this,
c() { return [1].map(() => this.ten)[0]; },
};
console.log(obj.a()); // ?
console.log(obj.c()); // ?Cả obj.a() và obj.c() đều cho 'A': ở a, this là obj vì gọi bằng dấu chấm; ở c, arrow function bên trong mượn this của phương thức bao ngoài. Riêng b là arrow function ở cấp module hoặc toàn cục nên this không phải obj. Việc tự đoán trước khi chạy giúp bạn rèn phản xạ rất tốt.
Hãy nhớ câu hỏi chính: "hàm này được gọi như thế nào?". Với arrow function thì câu hỏi là: "nó được viết ở đâu?". Chỉ cần vậy, bạn đã giải thích được đa số trường hợp this gây khó chịu.
Bạn có thể ôn tập chủ đề này cùng nhiều khái niệm JavaScript cốt lõi khác trong các khóa học tại codebem.com.
Nguyễn Đình Cường
0 comment