2009-08-05 35 views
49

Tôi đã sử dụng JSLint để làm cho tôi cảm thấy xấu về JavaScript của mình. Nó là tuyệt vời, bằng cách này. Có một kiểm tra mà tôi không hoàn toàn hiểu và tôi muốn quan điểm của bạn, xin vui lòng.Một var cho mỗi hàm trong JavaScript?

Từ jslint.com:

Trong các ngôn ngữ với phạm vi khối, nó thường được khuyến cáo rằng các biến được khai báo tại trang web sử dụng đầu tiên. Nhưng vì JavaScript không có phạm vi khối, nên khôn ngoan hơn là khai báo tất cả các biến của hàm ở đầu hàm. Nên sử dụng một câu lệnh var duy nhất cho mỗi hàm.

Lời cảm ơn cuối cùng thực sự là gì? Tôi nghĩ tôi nên khai báo nhiều biến như thế này?

var foo = 1, bar = 2; 

Và, phần "khôn ngoan" chỉ là một kiểu lập trình để ngăn chặn lỗi xuống dòng hoặc có nhiều lỗi hơn không?

Cảm ơn sự giúp đỡ của bạn.

+0

Tôi đã có hai câu trả lời tuyệt vời từ http://stackoverflow.com/users/5445/cms và http://stackoverflow.com/users/51101/breton. Tôi cảm thấy rằng cả hai đều trả lời câu hỏi này. Làm thế nào tôi có thể cung cấp tín dụng cho cả hai? : ( –

+7

Nhân tiện, nếu bạn thực sự muốn cảm thấy xấu về mã của mình, hãy thử đọc mã nguồn cho JSLINT và tìm hiểu cách nó hoạt động. Nó hoàn toàn đơn giản và dễ đọc, nhưng vẫn bí ẩn. Nó giống như tìm ra vũ trụ một fractal tính bằng phương trình 2 + 2 =? – Breton

+0

Có ai không có công cụ sẽ tự động định dạng lại mã cho một var cho mỗi kiểu hàm không? (nhưng không giảm bớt) – jlarson

Trả lời

71

Vấn đề là, cho dù bạn có nhận ra hay không, javascript di chuyển vô hình tất cả các khai báo var đến đầu phạm vi chức năng.

vì vậy nếu bạn có một chức năng như

var i = 5; 
function testvar() { 
    alert(i); 
    var i=3; 
} 
testvar(); 

cửa sổ cảnh báo này sẽ chứa không xác định. bởi vì nội bộ, nó đã được thay đổi thành điều này:

var i = 5; 
function testvar() { 
    var i; 
    alert(i); 
    i=3; 
} 
testvar(); 

điều này được gọi là "cẩu". Lý do crockford ủng hộ mạnh mẽ các khai báo var ở trên cùng, là nó làm cho mã phù hợp rõ ràng với những gì nó sẽ làm, thay vì cho phép hành vi vô hình và bất ngờ xảy ra.

+0

Thú vị - không bao giờ thực sự biết về JS - tất nhiên, tôi thường định nghĩa tất cả các biến của tôi ở trên cùng, và hiếm khi sử dụng lại tên biến từ vòng lặp/hàm ngoài. – gnarf

+0

Điều này thật thú vị nhưng không thực sự liên quan đến phạm vi chặn. – Triptych

+0

Nhưng nó là một câu trả lời hợp lệ cho câu hỏi của tôi ... –

8

Về cơ bản trong các khối JavaScript ({ ... }) không giới thiệu phạm vi mới, chỉ có phạm vi chức năng, do đó không phạm vi nào được tạo trên bất kỳ tuyên bố nào khác.

Biến được giới thiệu ở bất kỳ đâu trong hàm có thể hiển thị ở mọi nơi trong hàm.

Ví dụ:

function myFunction(){ 
    var one = 1; 

    if (one){ 
    var two = one + 1; 
    } 

    (function() { 
    var three = one + two; 
    })(); 

    // at this point both variables *one* and *two* are accessible but 
    // the variable *three* was declared in the scope of a inner function 
    // and is not accessible at this point. 
} 

Trong các ngôn ngữ với phạm vi khối, nó khuyến khích để khai báo các biến tại thời điểm sử dụng đầu tiên, nhưng vì JavaScript không có phạm vi khối, nó là tốt hơn để khai báo tất cả của một các biến của hàm ở trên cùng của hàm.

Kiểm tra điều này article.

+2

Bạn không thực sự giải thích lý do tại sao nó tốt hơn mặc dù nó cuối cùng theo từ chức năng chỉ phạm vi đó tốt hơn cho các vars ở trên đầu, nhưng bạn đã bỏ qua các bước lý luận từ thực tế đó, đến kết luận của bạn – Breton

+3

Tôi vừa đọc bài báo mà bạn liên kết đến, và nó cũng mắc phải sai lầm giống như Chetan. redeclaring var là một NOOP. Nó là hoàn toàn lành tính và không gây ra bất kỳ vấn đề. Đó là không nói rằng hạn chế bản thân để một tuyên bố var là vô ích, nhưng bạn, cũng không phải bài báo, đã thực sự làm cho một trường hợp thuyết phục cho nó. – Breton

+0

@Breton, nó có thể gây ra vấn đề bởi vì nó thường là một sự phản ánh của một lập trình nhầm lẫn. Nó cũng có thể gây nhầm lẫn cho các lập trình viên khác, những người làm điều hợp lý và đặt tất cả các vars là đỉnh của hàm. – Nosredna

4

Có, điều đó có nghĩa là bạn khai báo tất cả các biến ở đầu hàm. Cho dù bạn muốn làm điều đó trong một dòng hoặc nhiều dòng là một vấn đề của sự lựa chọn.

Lý do được giải thích trong đoạn bạn đã đề cập. Biến Javascript chỉ có phạm vi cấp chức năng. Nếu bạn khai báo cùng một biến bên trong một khối if/while/for, nó sẽ bị ghi đè bởi giá trị mới vì khối không mang một phạm vi mới. Điều này khác với các ngôn ngữ như Java. Để tránh những điều bất ngờ như vậy, hãy khai báo tất cả các biến bạn sẽ sử dụng trong hàm ở đầu hàm để bạn không vô tình 'redeclare' andything.

+0

Tôi không nghĩ rằng redeclaring một biến là vấn đề. Điều đó không ném một lỗi như trong C (hoặc java?). Trong thực tế nó không có gì. – Breton

+0

Xin lỗi, tôi phải rõ ràng hơn. Những gì tôi có nghĩa là tuyên bố cùng một tên biến bên trong một khối, được cho phép trong Java. Biến mới này chỉ tồn tại bên trong khối. –

+0

Ah vâng, tôi cho rằng đó sẽ là một vấn đề nếu bạn đã quen với một ngôn ngữ có phạm vi khối. – Breton

6

Việc thiếu phạm vi khối giải thích đoạn code dưới đây:

var a = 1; 
if (something) { 
    var a = 2; 
} 

alert(a); // Alerts "2" 

Trong hầu hết các C-phong cách (như trong cú pháp) ngôn ngữ, định nghĩa var a = 2 sẽ xác định 'a' chỉ dành cho phạm vi của khối if. Sử dụng một câu lệnh var duy nhất ở phía trên cùng của hàm sẽ giúp tránh sự lừa đảo này của Javascript, mà không phải lúc nào cũng rõ ràng như trên, và sẽ là bất ngờ đối với các lập trình viên C/C#/Java.

Các vấn đề liên quan