Hàm trong JavaScript: function, arrow function và phạm vi biến

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

Hàm là khối xây dựng quan trọng nhất của JavaScript. Bạn dùng hàm để gom một đoạn logic lại, đặt tên và gọi lại bao nhiêu lần tùy ý. Nắm vững cách viết hàm, phân biệt arrow function với function thường và hiểu phạm vi biến sẽ giúp bạn đọc hiểu hầu hết mã JavaScript hiện đại.

Các cách khai báo hàm

// 1. Khai báo hàm
function tinhTong(a, b) {
  return a + b;
}

// 2. Biểu thức hàm
const nhan = function (a, b) {
  return a * b;
};

// 3. Arrow function
const tru = (a, b) => a - b;

Cả ba đều gọi giống nhau: tinhTong(2, 3). Khác biệt chính: khai báo hàm được "hoisting", tức dùng được trước dòng khai báo trong cùng phạm vi, còn biểu thức hàm và arrow function thì không. Với arrow function, nếu thân hàm chỉ có một biểu thức, bạn có thể bỏ dấu ngoặc nhọn và từ khóa return, giá trị sẽ được trả về ngầm.

Tham số và giá trị mặc định

function chao(ten = 'bạn', loiChao = 'Xin chào') {
  return loiChao + ', ' + ten + '!';
}

chao();            // 'Xin chào, bạn!'
chao('Lan');       // 'Xin chào, Lan!'
chao('Nam', 'Chào'); // 'Chào, Nam!'

Giá trị mặc định chỉ được dùng khi đối số là undefined. Bạn cũng có thể nhận số lượng đối số tùy ý với tham số rest:

function tong(...cacSo) {
  return cacSo.reduce((acc, x) => acc + x, 0);
}
tong(1, 2, 3, 4); // 10

Phạm vi biến (scope)

Phạm vi quyết định biến nào nhìn thấy được ở đâu. Với let và const, phạm vi là khối lệnh (cặp ngoặc nhọn gần nhất):

function demo() {
  const a = 1;
  if (true) {
    const b = 2;
    console.log(a, b); // 1 2
  }
  console.log(a);      // 1
  // console.log(b);   // ReferenceError: b không tồn tại ở đây
}

Hàm bên trong nhìn thấy biến của hàm bên ngoài, nhưng không ngược lại. Quy tắc này gọi là chuỗi phạm vi (scope chain): JavaScript tìm biến ở phạm vi hiện tại, nếu không có thì tìm ra phạm vi bao ngoài, cứ thế đến phạm vi toàn cục.

Hạn chế biến toàn cục là thói quen tốt, vì chúng dễ bị ghi đè nhầm và khiến mã khó theo dõi.

Arrow function khác function thường ở đâu?

  • Cú pháp ngắn hơn, rất hợp với callback như arr.map(x => x * 2).
  • Không có this riêng: nó lấy this của phạm vi bao quanh. Điều này thuận tiện trong nhiều trường hợp, nhưng khiến arrow function không phù hợp để làm phương thức của đối tượng khi bạn cần this trỏ vào đối tượng đó.
  • Không có đối tượng arguments và không dùng làm hàm khởi tạo với new.

Hàm là giá trị

Trong JavaScript, hàm có thể gán cho biến, truyền làm đối số và trả về từ hàm khác. Đây là nền tảng của callback và lập trình hàm:

function thucHienNhieuLan(n, hanhDong) {
  for (let i = 0; i < n; i++) {
    hanhDong(i);
  }
}

thucHienNhieuLan(3, (i) => console.log('Lần ' + (i + 1)));

Hàm nhận hàm khác làm đối số được gọi là hàm bậc cao. Các phương thức mảng như map, filter, forEach đều thuộc loại này.

Thói quen viết hàm tốt

  1. Mỗi hàm làm một việc và có tên động từ rõ ràng, như tinhTongTien.
  2. Giữ số tham số ít, nếu quá bốn thì cân nhắc truyền một đối tượng.
  3. Hạn chế tác dụng phụ: hàm nên trả về giá trị thay vì sửa biến bên ngoài.
  4. Trả về sớm (early return) để tránh nhiều tầng if lồng nhau.

Ví dụ thực tế: hàm với callback và xử lý lỗi

Để thấy hàm kết hợp với nhau như thế nào, hãy xem một hàm kiểm tra đầu vào, nhận một hàm xử lý khi thành công:

function xuLyTuoi(tuoi, khiHopLe) {
  if (typeof tuoi !== 'number' || tuoi < 0) {
    return 'Tuổi không hợp lệ';
  }
  return khiHopLe(tuoi);
}

const ketQua = xuLyTuoi(18, (t) => 'Bạn ' + t + ' tuổi');
console.log(ketQua); // 'Bạn 18 tuổi'

Chú ý cách ta trả về sớm khi dữ liệu sai: phần xử lý chính nằm gọn ở cuối hàm, không bị lồng sâu. Bạn cũng nên biết thêm về IIFE (hàm gọi ngay) và closure, hai khái niệm nâng cao sẽ giúp bạn hiểu hàm sâu hơn sau khi đã quen với nền tảng ở đây.

Kết luận

Bạn đã biết ba cách khai báo hàm, tham số mặc định và rest, phạm vi khối, sự khác biệt của arrow function và việc coi hàm như một giá trị. Hãy luyện tập bằng cách tách các đoạn code dài thành nhiều hàm nhỏ có tên rõ ràng.

Để thực hành hàm và các khái niệm JavaScript khác qua bài tập thực tế, hãy ghé các khóa học tại codebem.com khi bạn cần một lộ trình có sẵn.

author_photo
Nguyễn Đình Cường

0 comment