Arrow function (fat arrow) giải quyết vấn đề lexical binding "this". Arrow function không có this riêng, nó kế thừa this từ scope bao quanh (lexical scope). Cú pháp => gọi là fat arrow.
Vấn đề với function thường
$('.button1').click(function () {
setTimeout(function () {
$(this).text('demo'); // ❌ LỖI: 'this' ở đây là global object (window) hoặc undefined (strict mode)
}, 400);
});
Function thường (function() {}) tự tạo this riêng. Trong setTimeout, this mất context gốc.
Giải quyết với Arrow Function
$('.button1').click(function () {
setTimeout(() => {
$(this).text('demo'); // ✅ 'this' lexical từ click handler (element .button1)
}, 400);
});
Lexical Scoping (Static Scoping)
JavaScript dùng lexical scoping: scope được xác định bởi vị trí viết code (static), không phải nơi gọi (dynamic).
- Arrow function: không có this, arguments, super, new.target riêng → lookup trong scope cha.
- Function thường: có this riêng → được xác định bởi cách gọi (call site).
Các cách fix "this" trước ES6
// 1. var self = this (thường dùng)
$('.button1').click(function () {
var self = this;
setTimeout(function () {
$(self).text('demo');
}, 400);
});
// 2. .bind(this)
$('.button1').click(function () {
setTimeout(function () {
$(this).text('demo');
}.bind(this), 400);
});
// 3. Arrow function (ES6) - clean nhất
$('.button1').click(() => {
setTimeout(() => {
$(this).text('demo');
}, 400);
});
Khi KHÔNG nên dùng Arrow Function
- Object methods:
const obj = { method: () => { console.log(this) } }→thislà global, không phảiobj. - Constructor:
const Person = () => { this.name = 'A' }→ không dùngnewđược. - Prototype methods:
Class.prototype.method = () => {}→thissai. - Event handlers cần this = element:
el.addEventListener('click', () => { this })→thiskhông phảiel.
Tóm tắt
Lexical this = this được xác định bởi vị trí định nghĩa (scope cha), không phải cách gọi. Arrow function cung cấp lexical this tự nhiên, code ngắn gọn, tránh bug this klassischen.