Biểu thức hàm có tên trong JavaScript

Giả sử chúng ta có một biểu thức hàm như sau:

javascriptlet test = function() {
  console.log('!');
};

test(); // sẽ in ra '!'

Hãy đặt tên cho hàm của chúng ta là func:

javascriptlet test = function func() {
  console.log('!');
};

test();

Như bạn đã biết, không thể truy cập hàm bằng tên này:

javascriptlet test = function func() {
  console.log('!');
};

test(); // sẽ in ra '!'
func(); // sẽ báo lỗi

Vậy tại sao lại đặt tên cho hàm nếu nó không thể truy cập được? Vấn đề là tên này sẽ không thể truy cập từ bên ngoài hàm, nhưng có thể truy cập được bên trong hàm đó.

Hãy kiểm tra:

javascriptlet test = function func() {
  console.log(func); // hàm sẽ in ra mã nguồn của chính nó
};

test(); // gọi hàm

Hãy gọi hàm của chúng ta bên trong chính nó:

javascriptlet test = function func() {
  console.log('!'); // in ra '!'
  func(); // gọi chính chúng ta
};

test();

Nếu chạy mã này, một số lượng vô hạn các kết quả sẽ được in ra bảng điều khiển.

Thực tế, hàm của chúng ta có thể được gọi bên trong chính nó không chỉ là func, mà còn là test:

javascriptlet test = function func() {
  console.log('!');
  test(); // gọi chính chúng ta
};

test();

Vậy sự khác biệt là gì? Sự khác biệt là tên test - chỉ đơn giản là một biến. Trong quá trình chạy script, hàm của chúng ta có thể được gán vào một biến khác hoặc truyền dưới dạng tham số - trong trường hợp này, mối liên hệ giữa biến test và hàm có thể bị mất.

Còn tên func thì được gắn cứng với hàm một cách đặc biệt để có thể tham chiếu đến hàm của chúng ta bên trong chính nó.

Những Function Expression có tên hàm như vậy được gọi là biểu thức hàm có tên.