Hàm khai báo là var thay vì hàm


28

Càng ngày tôi càng thấy các hàm được khai báo như

var foo = function() {

    // things
};

Thay vì cách tôi đã học, như

function foo() {

    // things
}

Có gì khác biệt? Hiệu suất tốt hơn? Phạm vi? Tôi có nên sử dụng phương pháp này?


Điều đáng chú ý là trong javascript, các hàm là công dân hạng nhất . Điều này cho phép bạn vượt qua hành vi giống như các đối tượng. Điều này rất hữu ích cho các cuộc gọi lại và ủy quyền, trong số những thứ khác.
Chris Bye

Phạm vi . Gói biến tên "// thing" về cơ bản / hy vọng ngăn chặn sự va chạm tên của "// thứ" mà nó bao bọc, với các JavaScript (tệp) khác được bao gồm. Một cách khác để nghĩ về nó là bạn đã tạo ra một không gian tên "foo".
radarbob

Câu trả lời:


25

var foo = function() {} định nghĩa một biến tham chiếu đến một hàm ẩn danh.

function foo() {}định nghĩa một hàm được đặt tên foo.

Hoặc có thể được truyền bằng tên dưới dạng tham số chức năng và có thể được khởi tạo nếu mục đích sử dụng là dành cho OOP.

Vào cuối ngày, cái nào bạn sử dụng phần lớn được quyết định bởi trường hợp sử dụng cụ thể của bạn (Javascript rất thú vị như thế;)). Nếu bạn kết thúc bằng cách sử dụng cũ, tôi sẽ mạnh mẽ đề nghị bạn nên đặt tên cho chức năng:

var foo = function MY_function() {}. Quy ước đặt tên này giúp cho trình gỡ lỗi trình gỡ lỗi của bạn không bị vô dụng.


1
Có một chức năng ở đó trên chức năng () MY ...
Erik Reppen

1
@Dppy Brecht, còn cách tiếp cận var foo = function foo () {...} thì sao?
shabunc

@shabunc: Thế còn nó? Nó được liệt kê trong đoạn cuối câu trả lời của tôi.
Demian Brecht

@Dppy Brecht, không, thực sự trong biến đoạn cuối được gọi foovà hàm được gọiMY_function
shabunc

@shabunc: Tên không quan trọng. Điều quan trọng là giá trị trong Callstack. Ví dụ: [NnamPACE] _ [tên fn] là quy ước được sử dụng bởi Mozilla. Tên của nó không quan trọng miễn là quy ước của bạn nhất quán trong suốt dự án của bạn.
Demian Brecht

13

biểu thức hàm:

//someFunction(); //wouldn't work when uncommented
var someFunction = function(){ alert('yay'); };

Biểu thức func trong trường hợp này là ẩn danh nhưng được gán cho một var để tham khảo. Điều này khác với một tuyên bố chức năng được dán nhãn theo các cách sau:

  • nó không thể được nâng lên (được gọi trước khi nó được xác định)
  • new someFunction().constructor.name === 'someFunction';//false Các trường hợp không nhận được tên var cho constructor.name vì tham chiếu đến hàm được gán cho var nhưng var, không phải hàm, được gắn với tên var

Trong một tuyên bố chức năng được dán nhãn:

//someFunction(); //works when uncommented
function someFunction(){ alert('yay'); }
  • cẩu công trình
  • new someFunction().constructor.name === 'someFunction'; //true tên được gắn trực tiếp vào chức năng.

Nói chung, thực sự không có bất kỳ lý do tuyệt vời nào để thực hiện biểu thức cho var trừ khi bạn muốn các cuộc gọi thất bại nếu mọi thứ bị di chuyển xung quanh hoặc bạn đang xác định / gán một phương thức trong một dòng. Tôi thực sự thấy việc nâng hàng hữu ích cho việc tổ chức các đối tượng với các định nghĩa phương thức và phương thức bên trong ở phía dưới để tôi có thể có được hành vi thực tế của đối tượng và thực hiện các định nghĩa phương thức công khai một dòng (chỉ bằng cách gán funcs this.với cùng tên) tại chỗ để dễ tham khảo. Bạn phải luôn cố gắng sử dụng các câu lệnh được gắn nhãn cho các hàm tạo, IMO, để bạn có thể xác định 'loại' của đối tượng thông qua hàm tạo của nó.


8

Ví dụ đầu tiên của bạn là một biểu thức trong khi ví dụ thứ hai là một câu lệnh . Xác định các hàm làm biểu thức cho phép linh hoạt hơn trong đó định nghĩa có thể xảy ra, những gì bạn có thể gán cho nó, rằng bạn có thể chuyển nó dưới dạng tham số, v.v ...

Ví dụ:

SomeThing('abc', function(a,b) {return a*b;});

đấu với ...

function tmp(a,b) { 
    return a*b;
}

SomeThing('abc', tmp);

Các ví dụ phức tạp hơn sẽ trở nên phức tạp một cách khó hiểu nếu không có cú pháp biểu thức hàm.

Hãy xem https://stackoverflow.com/questions/111102/how-do-javascript-closures-work


4

Sự khác biệt thực tế chính là cẩu. Ví dụ:

foo(); // alerts 'hello'
function foo() {alert('hello');}

đấu với

foo(); // throws an error since foo is undefined
var foo = function() {alert('hello');}

Ngoài ra, đây là hành vi không xác định

function foo(){
  if (true) {
    function bar(){}
  }
  bar();
}

trong khi điều này là ok

function foo(){
  if (true) {
    var bar = function(){}
  }
  bar();
}

7
Hoàn toàn không có gì sai khi định nghĩa một hàm bên trong một hàm trong JS. Không có nhiều nơi bạn không thể định nghĩa một hàm trong JS.
Erik Reppen

2
@ErikReppen Bạn chắc chắn không thể sử dụng khai báo hàm trong các khối không có chức năng (như trong câu lệnh if). Tôi dường như không thể tìm thấy nơi tôi đọc chúng không thể được sử dụng trong một chức năng khác.
Austin

@Austin Không có gì sai với định nghĩa hàm trong một ifcâu lệnh!
Tim

@Austin: Có lẽ bạn đọc nó tại w3schools? ;)
Demian Brecht

2
@ErikReppen Biểu thức hàm có thể được sử dụng ở bất cứ đâu. Khai báo hàm không thể. Xem stackoverflow.com/questions/10069204/ Mạnh
Austin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.