2011-11-10 21 views
9

Tôi nhận thấy một kết quả thú vị từ JSLint trong khi nghiên cứu câu hỏi codereview. JSLint đã phàn nàn rằng một biến là được sử dụng trước khi được xác định. Dưới đây là một phiên bản rút gọn của mã mà tạo ra kết quả tương tự:var từ khóa trong các biểu thức try/catch: lỗi JSLint hoặc gán toàn cầu?

(function() { 
    try { 
     var a = 0; 
     throw { name: "fakeError" }; 
    } catch (e) { 
     a = 1; 
    } 
}()); 

sự hiểu biết của tôi về Javascript nói rằng các mã trên nên được tương đương với:

(function() { 
    var a; 
    try { 
     a = 0; 
     throw { name: "fakeError" }; 
    } catch (e) { 
     a = 1; 
    } 
}()); 

và trên thực tế, không phải ví dụ gây a để tồn tại trong phạm vi toàn cầu khi chạy qua Firebug. Tôi đã xem phần 12.14 của số ECMA-262 spec, nhưng tôi không thấy bất cứ điều gì khiến tôi nghĩ rằng các chức năng cần được xử lý khác nhau. Đây có phải chỉ là một lỗi trong JSLint, hoặc là hai biểu thức khác nhau trong một số cách chức năng?

Trả lời

5

Nó chỉ là một lỗi, nhưng tùy chọn mặc định của JSLint sẽ thích nó hơn nếu bạn di chuyển tất cả các câu lệnh var của bạn lên trên cùng.

1

Trong khi kèm theo một số khối mã trong dấu ngoặc nhọn {...} chỉ đơn thuần là không tạo ra một phạm vi mới trong javascript, catch là một ngoại lệ như đã nêu trong ECMAScript 5 spec. Mã bên trong khối catch có một phạm vi khác so với mã bên ngoài. điều trị của nó giống như phạm vi bên trong hàm.

Nói cách khác, như đã nêu here:

Khối catch là duy nhất ở chỗ JavaScript tạo định danh này khi khối catch được nhập và nó sẽ thêm nó vào phạm vi hiện hành; định danh chỉ kéo dài trong khoảng thời gian của khối catch; sau khi khối catch kết thúc thực thi, mã định danh không còn tồn tại nữa.

function f() { 
    try { 
    throw "foo"; 
    } catch (e) { 
    } 
    // e undefined here 
} 

Và như bạn đã biết, chúng ta không thể mong đợi cẩu biến từ 2 phạm vi khác nhau của mã trong javascript. Vì vậy, JSLint phàn nàn vì anh ta/cô ấy ;-) biết điều này.

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