ES6 (ECMAScript 2015) đã giới thiệu một cú pháp hàm mới gọi là Arrow Function (hàm mũi tên). Tên gọi này bắt nguồn từ ký hiệu => được sử dụng để định nghĩa hàm.
Ví dụ cơ bản:
// Arrow Function
const double = x => x * 2;
// Tương đương với hàm thông thường
const doubleRegular = function(x) {
return x * 2;
};
Arrow Function hoạt động như một hàm ẩn danh (anonymous function) nhưng có cú pháp ngắn gọn hơn. Có hai dạng chính:
Dạng biểu thức đơn (single expression): Không cần dùng từ khóa
returnvà dấu ngoặc nhọn.// Chỉ một tham số, thực thi một biểu thức const square = x => x * x;Dạng nhiều câu lệnh: Cần dùng
{ }và từ khóareturn.const processValue = x => { if (x > 0) { return x * x; } else { return -(x * x); } };
Cách xử lý tham số:
Khi có nhiều tham số hoặc không có tham số, cần dùng dấu ngoặc đơn:
// Hai tham số const sum = (a, b) => a + b; // Không tham số const getPi = () => 3.14159; // Tham số rest (phần còn lại) const sumAll = (a, b, ...others) => { let total = a + b; for (let num of others) { total += num; } return total; };
Trả về đối tượng (object):
Khi muốn trả về một object literal từ arrow function, cần bọc nó trong dấu ngoặc đơn để tránh nhầm lẫn với thân hàm:
// Sai - sẽ gây lỗi SyntaxError
const createUser = name => { username: name };
// Đúng - bọc object trong ()
const createUser = name => ({ username: name });
Giá trị của this trong Arrow Function
Khác biệt quan trọng nhất giữa arrow function và function thông thường nằm ở cách xử lý từ khóa this:
- Function thông thường:
thisđược xác định tại thời điểm gọi hàm (dynamic binding). - Arrow Function:
thisđược xác định dựa trên ngữ cảnh (lexical scope) tại nơi hàm được định nghĩa.
Ví dụ so sánh:
const person = {
birthYear: 1990,
getAge: function() {
// Sử dụng function thông thường - có vấn đề
const calculate = function() {
return new Date().getFullYear() - this.birthYear; // this không phải person
};
return calculate();
}
};
// Cách khắc phục với Arrow Function
const personFixed = {
birthYear: 1990,
getAge: function() {
const calculate = () => new Date().getFullYear() - this.birthYear; // this là person
return calculate();
}
};
console.log(personFixed.getAge()); // Kết quả đúng
Lưu ý quan trọng: Vì this trong arrow function đã được gắn kết theo lexical scope, nên các phương thức call(), apply(), bind() sẽ không thể thay đổi giá trị của this:
const person = {
birthYear: 1990,
getAge: function(year) {
const calculator = (y) => y - this.birthYear;
return calculator.call({birthYear: 2000}, year); // this vẫn là person, không phải {birthYear: 2000}
}
};
console.log(person.getAge(2023)); // Kết quả 33, không phải 23