Hàm là trái tim của JavaScript. Bài này trình bày hàm thường, hàm mũi tên, tham số mặc định và callback.
- Viết hàm theo hai cách
- Dùng hàm mũi tên (arrow function)
- Dùng tham số mặc định, rest
- Hiểu hàm có thể truyền như giá trị (callback)
- Hàm mũi tên
- Cách viết gọn:
(a, b) => a + b. - Callback
- Hàm được truyền vào hàm khác để gọi sau.
- Phạm vi (scope)
- Biến khai báo bằng let/const chỉ sống trong khối chứa nó.
- Closure
- Hàm nhớ được biến ở nơi nó được tạo ra.
Khái niệm và lý thuyết
Trong JavaScript, hàm là giá trị hạng nhất: có thể gán cho biến, đưa vào mảng, truyền làm đối số và trả về từ hàm khác. Đây là nền tảng của lập trình hàm và của cơ chế sự kiện, xử lý bất đồng bộ.
Callback là hàm được đưa cho hàm khác để "gọi lại" khi có việc xong, ví dụ setTimeout(f, 1000). Closure xảy ra khi hàm bên trong nhớ các biến của hàm bên ngoài ngay cả sau khi hàm ngoài đã kết thúc; nhờ đó ta tạo được biến "riêng tư" và các bộ đếm như ví dụ dưới đây.
Hàm mũi tên (a, b) => a + b ngắn gọn và không có this riêng, nó dùng this của nơi định nghĩa, phù hợp cho callback. Hàm thường (function) có this riêng tùy cách gọi, hợp cho phương thức của đối tượng.
Khai báo hàm
function chao(ten = "bạn") {
return `Xin chào ${ten}`;
}
console.log(chao("Lan"), chao());
const nhan = (a, b) => a * b;
const binhPhuong = x => x * x;
console.log(nhan(3, 4), binhPhuong(5));Tham số còn lại và spread
function tong(...so) {
return so.reduce((s, x) => s + x, 0);
}
console.log(tong(1, 2, 3, 4)); // 10
const a = [1, 2], b = [...a, 3, 4]; // [1,2,3,4]Ví dụ: hàm tính giá sau khuyến mãi
function giaSauGiam(gia, phanTram = 10) {
return gia * (1 - phanTram / 100);
}
const giam = gia => gia * 0.9; // hàm mũi tên
console.log(giaSauGiam(200000)); // 180000
console.log(giam(200000)); // 180000Hàm mũi tên viết gọn hơn và rất hay dùng làm đối số cho các hàm khác. Bạn có thể coi hàm là "một giá trị" như số hay chuỗi: truyền vào hàm khác, lưu vào biến, trả về từ hàm khác.
Callback
function lapLai(n, viec) {
for (let i = 0; i < n; i++) viec(i);
}
lapLai(3, i => console.log("Việc số", i));
setTimeout(() => console.log("Sau 1 giây"), 1000);Closure
function boDem() {
let dem = 0;
return () => ++dem;
}
const d = boDem();
console.log(d(), d(), d()); // 1 2 3Cửa hàng muốn lọc sản phẩm theo điều kiện thay đổi (dưới 200k, dưới 500k...). Hàm nhận điều kiện làm tham số giúp dùng lại:
const loc = (ds, dk) => ds.filter(dk);
console.log(loc([120, 340, 90], g => g < 200)); // [120, 90]Hàm một dòng ngắn dùng mũi tên; hàm dài, cần tên rõ ràng, dùng function.
Hàm mũi tên không có this riêng; trong phương thức đối tượng cần cân nhắc.
- Viết hàm đảo ngược chuỗi.
- Viết hàm
demNguyenAm(chuoi). - Dùng
setIntervalin thời gian mỗi giây, dừng sau 5 lần.
- Hàm có thể là giá trị: gán biến, truyền, trả về.
- Mũi tên viết gọn, tham số mặc định tiện lợi.
- Callback và closure là nền tảng của lập trình bất đồng bộ.