Trong trường hợp của biểu thức hàm ẩn danh, hàm là ẩn danh - theo nghĩa đen, nó không có tên. Biến mà bạn đang gán nó có tên, nhưng hàm thì không. (Cập nhật: Điều đó đúng thông qua ES5. Kể từ ES2015 [hay còn gọi là ES6], thường một hàm được tạo bằng biểu thức ẩn danh sẽ nhận được tên đúng [nhưng không phải là số nhận dạng tự động], hãy đọc tiếp ...)
Tên rất hữu ích. Tên có thể được nhìn thấy trong dấu vết ngăn xếp, ngăn xếp cuộc gọi, danh sách các điểm ngắt, v.v. Tên là một Điều tốt ™.
(Bạn đã từng phải cẩn thận với các biểu thức hàm được đặt tên trong các phiên bản IE cũ hơn [IE8 trở xuống], vì chúng đã tạo nhầm hai đối tượng hàm hoàn toàn riêng biệt vào hai thời điểm hoàn toàn khác nhau [thêm trong bài viết blog Double take của tôi ]. Nếu bạn cần hỗ trợ IE8 [!!], có lẽ tốt nhất nên sử dụng các biểu thức hàm ẩn danh hoặc khai báo hàm , nhưng tránh các biểu thức hàm được đặt tên.)
Một điều quan trọng về biểu thức hàm được đặt tên là nó tạo một mã định danh trong phạm vi có tên đó cho hàm trong phần thân hàm:
var x = function example() {
console.log(typeof example); // "function"
};
x();
console.log(typeof example); // "undefined"
Tuy nhiên, kể từ ES2015, rất nhiều biểu thức hàm "ẩn danh" tạo ra các hàm có tên và điều này đã có trước bởi các công cụ JavaScript hiện đại khác khá thông minh trong việc suy ra tên từ ngữ cảnh. Trong ES2015, biểu thức hàm ẩn danh của bạn dẫn đến một hàm có tên boo
. Tuy nhiên, ngay cả với ngữ nghĩa ES2015 +, số nhận dạng tự động không được tạo:
var obj = {
x: function() {
console.log(typeof x); // "undefined"
console.log(obj.x.name); // "x"
},
y: function y() {
console.log(typeof y); // "function"
console.log(obj.y.name); // "y"
}
};
obj.x();
obj.y();
Việc gán cho tên của hàm được thực hiện với hoạt động trừu tượng SetFunctionName được sử dụng trong các hoạt động khác nhau trong đặc tả.
Phiên bản ngắn về cơ bản là bất cứ khi nào một biểu thức hàm ẩn danh xuất hiện ở phía bên phải của một cái gì đó như một phép gán hoặc khởi tạo, như:
var boo = function() { /*...*/ };
(hoặc có thể là let
hoặc const
đúng hơn var
) , hoặc
var obj = {
boo: function() { /*...*/ }
};
hoặc là
doSomething({
boo: function() { /*...*/ }
});
(hai hàm cuối cùng thực sự giống nhau) , hàm kết quả sẽ có tên ( boo
, trong các ví dụ).
Có một ngoại lệ quan trọng và có chủ đích: Gán cho một thuộc tính trên một đối tượng hiện có:
obj.boo = function() { /*...*/ }; // <== Does not get a name
Điều này là do lo ngại về rò rỉ thông tin được đưa ra khi tính năng mới đang trong quá trình được thêm vào; chi tiết trong câu trả lời của tôi cho một câu hỏi khác ở đây .