2009-07-22 3 views
12

Tôi có một số mã như sau:Có gì sai khi xác định các biến JavaScript trong các khối?

if (condition) { 
var variable = blah; 
} 

if (differentcondition) { 
var variable = blah; 
} 

Điều này có đúng không?

Tôi giả định rằng biến sẽ không được gán nếu điều kiện không trả về đúng.

JSLint tiếp tục cho tôi biết, biến đã được xác định.

Tôi có làm điều này sai không?

Cảm ơn.

OK, Dưới đây là usecase thực tế của tôi, tôi đang làm đoàn sự kiện như thế này:

$("#container").click(function (event){ 

    if ($(event.target).is('img.class1')) { 
     var imagesrc = $(event.target).attr('src'); 
     // Do something with imagesrc 
    } 

    if ($(event.target).is('img.class2')) { 
     var imagesrc = $(event.target).attr('src'); 
     // Do something with imagesrc 
    } 

    // This condition is mutually exclusive to the above 2 
    if ($(event.target).is('img.class3')) { 
     var imagesrc = $(event.target).attr('src'); 
     // Do something with imagesrc 
    } 

    // This condition is mutually exclusive to 1 and 2 but not to 3 
    if ($(event.target).is('img.class4')) { 
     var imagesrc = $(event.target).attr('src'); 
     // Do something with imagesrc 
    } 

}); 

Trên thực tế những 2 lớp này không loại trừ lẫn nhau.

Điều này phù hợp với tôi, nhưng có đúng không?

Câu trả lời rất thông tin, nhưng tôi vẫn không hiểu cách tôi nên thiết lập các biến tại đây.

Thực ra tôi cũng muốn nói rằng một số điều kiện nhất định là loại trừ lẫn nhau và một số điều kiện nhất định là không.

Tôi nên cấu trúc như thế nào?

Tôi có lẽ đã sử dụng ví dụ này ngay từ đầu.

+0

Tôi sẽ sử dụng phương pháp này: var variable = (điều kiện)? "foo": "bar"; – Roi

Trả lời

31

Vì javascript có cái gì gọi là "tời kéo" mà làm cho mã của bạn làm những điều nó không giống như nó nên làm. Về cơ bản, điều đó có nghĩa là một trình thông dịch javascript sẽ di chuyển tất cả các khai báo var, bất kể chúng ở đâu trong phần thân của một hàm, ở trên cùng của thân hàm. Sau đó, nó sẽ di chuyển tất cả các định nghĩa chức năng lên đầu, ngay dưới tất cả các vars. Sau đó, nó sẽ hoàn thành việc biên dịch hàm.

Đặt một var bên trong câu lệnh if không phải là "quy tắc" của ngôn ngữ, nhưng nó có nghĩa là, vì var hoisting, var đó sẽ được xác định bất kể điều kiện của câu lệnh if có được thỏa mãn hay không. Hãy nhớ rằng việc nâng cẩu không bao gồm nhiệm vụ, như những người khác đã chỉ ra, các khai báo var sẽ được di chuyển lên trên cùng và không được xác định cho đến khi chúng được gán sau này.

Đây là ví dụ về một đối tượng địa lý phải có vẻ như là một ý tưởng hay vào thời điểm đó, nhưng điều đó hóa ra lại khó hiểu hơn là hữu ích.

+0

Cảm ơn bạn, wow. Vì vậy, nhiều câu trả lời tốt, tôi không biết cái nào để chọn. – Mark

+0

đó là một tính năng khó hiểu, nhưng sẽ khó hiểu hơn nếu bạn có thể kết hợp phạm vi chức năng và khối. – worc

+0

@worc Hãy để sự nhầm lẫn bị treo! [pun dự định]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let –

12

Điều này là do trong JavaScript, các biến chỉ có phạm vi khác nhau trong các khối chức năng. Không giống như các ngôn ngữ khác, nếu khối không có một phạm vi khác nhau trong JavaScript.

Trong trường hợp của bạn, JSLint sẽ cho bạn biết biến đã được xác định vì có thể cả hai điều kiện đều đúng, trong trường hợp này bạn sẽ ghi đè biến của mình.

Dưới đây là một ví dụ về cách phạm vi hoạt động trong JavaScript:

function Something() { 
    var thing1 = "hello"; 

    (function() { 
     var thing2 = "world"; 
    })(); 

    // This line will throw a ReferenceError because "thing2" is not defined in this scope 
    // It only exists within the scope of the function executed above 
    alert(thing1 + thing2); 
} 

function SomethingElse() { 
    var thing1 = "hello"; 

    if(true) { 
     var thing2 = "world"; 
    } 

    // This line will work because thing2 is not limited to the if-block 
    alert(thing1 + thing2); 
} 
+2

+1. Bên cạnh đó, bạn nên đặt tên biến của bạn một cái gì đó có ý nghĩa, không chỉ là "biến" (đó là anyways xấu, bởi vì nó có thể là một từ khóa dành riêng trong một số ngôn ngữ). – jkeys

+0

Có, cảm ơn rất nhiều. Tôi cũng muốn biết liệu tôi có nên thay đổi mã của mình vì trường hợp sử dụng của tôi không phải là trường hợp cả hai sẽ trả về đúng sự thật. – Mark

+0

Tôi sẽ thay đổi mã. Nếu 2 điều kiện loại trừ lẫn nhau, thì bạn nên cân nhắc việc tái cơ cấu mã để sử dụng if-else, không phải 2 ifs. –

0

là những điều kiện if-hai loại trừ lẫn nhau? Có lẽ bạn muốn sử dụng cấu trúc kiểm soát "khác":

if (condition) { 
    var variable = blah; 
} 
else if (differentcondition) { 
    var variable = blah; 
} 

Điều này có nghĩa là nếu điều kiện đầu tiên là đúng thì phần thứ hai của mã sẽ không bao giờ được thực thi.

Nói chung, nó tốt hơn để khai báo các biến trong cấu trúc mà họ đang được sử dụng trong Nếu biến chỉ nên tồn tại trong câu lệnh if, tuyên bố nó ở đó là tốt, nếu không, di chuyển nó ra ngoài như vậy:.

var variable; 
if (condition) { 
    variable = blah; 
} 
else if (differentcondition) { 
    variable = blah; 
} 
// continue to use variable here... 

Lưu ý: nếu bạn đang sử dụng các if riêng biệt mà không có người khác, thì trước tiên bạn sẽ cần phải đặt biến thành giá trị mặc định.

6

Chỉ các hàm tạo phạm vi bên trong. Nó thậm chí còn giống như trong ví dụ này.

var x = 2; 
function foo() { 
    alert(x); // will alert undefined?!? 

    var x = 4; 
} 
foo(); 
alert(x); // will alert 2 

Cảnh báo đầu tiên thực sự sẽ không được xác định. Tại sao?Vì tất cả các khởi tạo biến xảy ra trong hàm được khởi tạo thành không xác định tại đầu hàm. Đó là lý do tại sao Crockford nói để khởi tạo tất cả các biến càng sớm càng tốt.

Vì vậy, mã của bạn có lẽ nên trông như thế này:

$("#container").click(function (event){ 
     var imagesrc; 
     if ($(event.target).is('img.class1')) { 
       imagesrc = $(event.target).attr('src'); 
       // Do something with imagesrc 
     } 

     if ($(event.target).is('img.class2')) { 
       imagesrc = $(event.target).attr('src'); 
       // Do something with imagesrc 
     } 

     // This condition is mutually exclusive to the above 2 
     if ($(event.target).is('img.class3')) { 
       imagesrc = $(event.target).attr('src'); 
       // Do something with imagesrc 
     } 

     // This condition is mutually exclusive to 1 and 2 but not to 3 
     if ($(event.target).is('img.class4')) { 
       imagesrc = $(event.target).attr('src'); 
       // Do something with imagesrc 
     } 

}); 
+0

Tuyệt vời, cảm ơn! – Mark

0

Tôi nên cấu trúc điều này như thế nào?

Trong trường hợp này, có vẻ như nó sẽ là tốt hơn để tổ các điều kiện:

$("#container").click(function (event) { 
    if ($(event.target).is('img')) { 
     var imagesrc = $(event.target).attr('src'); 

     if ($(event.target).is('.class1')) { 
      // Do something with imagesrc 
     } 

     if ($(event.target).is('.class2')) { 
      // Do something with imagesrc 
     } 

     // This condition is mutually exclusive to the above 2 
     if ($(event.target).is('.class3')) { 
      // Do something with imagesrc 
     } 

     // This condition is mutually exclusive to 1 and 2 but not to 3 
     if ($(event.target).is('.class4')) { 
      // Do something with imagesrc 
     } 
    } 
}); 

Hoặc tốt hơn sử dụng đoàn sự kiện của jQuery:

$("#container").on("click", "img", function (event) { 
    var imagesrc = $(this).attr('src'); 

    if ($(this).is('.class1')) { 
     // Do something with imagesrc 
    } 

    if ($(this).is('.class2')) { 
     // Do something with imagesrc 
    } 

    // This condition is mutually exclusive to the above 2 
    if ($(this).is('.class3')) { 
     // Do something with imagesrc 
    } 

    // This condition is mutually exclusive to 1 and 2 but not to 3 
    if ($(this).is('img.class4')) { 
     // Do something with imagesrc 
    } 
});