2011-11-08 34 views
5

Điều sau đây gây nhầm lẫn cho tôi rất nhiều. Như đã lưu ý trong các nhận xét, các so sánh dường như hoạt động một mình, nhưng khi đặt lại với nhau, chúng khôngNhà điều hành "==" Javascript nằm

Thời gian sẽ chạy trong cùng một tháng, sau đó tăng từng cái một, sau đó bắt đầu lại.

Tôi đã đặt toàn bộ chuỗi với console.log để cố gắng tìm ra, nhưng nó không có ý nghĩa gì cả. Mọi thứ dường như bằng nhau, nhưng vẫn thất bại trong bài kiểm tra "==" trong câu lệnh while.

var i=0; 
    var currentdate = 0; 
    var currentmonth = 0; 
    var opensmonth = 0; 
    var opens = [ 
    { "date":"3/30/2006","zip":"30038","latitude":"33.676358","longitude":"-84.15381"}, 
    { "date":"4/31/2006","zip":"30519","latitude":"34.089419","longitude":"-83.94701"} 
    ]; 
    intid = setInterval("stepthrough()", 250); 
    function stepthrough() { 
    //figure out first date. 
    if (currentdate == 0) { // we've not been run before 
     currentdate = opens[0]["date"]; 
     currentmonth = currentdate.split("/", 1); 
     console.log("Current Month: >" + currentmonth +"<"); 
    } 
    console.log("Current month: " + currentmonth + " And opensdate: " + opens[i]["date"].split("/", 1)); 

    // 
    // TWILIGHT ZONE ENTERED. 
    // 
    if (currentmonth == 3) { 
     console.log("Current month equals 3."); // PASSES 
    } 
    if (opens[i]["date"].split("/", 1) == 3) { 
     console.log("Opens date equals 3."); // PASSES 
    } 
    // BOTH THE ABOVE TESTS PASS IN CHROME AND SAFARI WHAT THE F*$K JAVASCRIPT 

    while(opens[i]["date"].split("/", 1) == currentmonth) { // WHY DOESNT THIS WORK I HATE COMPUTERS 
     console.log("Trying to add a point one."); 
     addpoint(i); 
     i++; 
     console.log("Trying to add a point."); 
    } 

    //set the date for next iteration 
    currentdate = opens[i]["date"]; 
    currentmonth = currentdate.split("/", 1); 
    console.log ("Current date is now: " + currentdate + " and current month is now: " + currentmonth); 
    jQuery('div#date').text(currentdate); 

    //if (i>=5000) { 
    if (!opens[i]["date"]) { 
     console.log("Clearing interval"); 
     clearInterval(intid); 
     //jQuery('div#date').text("Limited at 5000 records") 
    } 
    } 
+3

thử sử dụng 'parseInt (stringValue, 10)'. –

+0

Điều gì sẽ xảy ra nếu bạn sử dụng '===' trong dòng '// WHY DOESNT NÀY LÀM VIỆC '? [Câu trả lời này] (http://stackoverflow.com/questions/359494/javascript-vs-does-it-matter-which-equal-operator-i-use/359509#359509) gợi ý rằng '==' là tà ác và không thể tin được. – CanSpice

+2

tôi thành thật không thấy câu hỏi ở đây. –

Trả lời

4

Đây là vấn đề: ["1"] == 1 trong Javascript, vì chuyển đổi ẩn @Matt mô tả. Nhưng ["1"] != ["1"] trong Javascript, bởi vì bạn đang so sánh hai mảng và do đó hai đối tượng và so sánh đối tượng chỉ đúng nếu chúng trỏ đến đối tượng cùng một đối tượng, không phải nếu chúng trỏ đến hai đối tượng giống nhau.

Khi bạn chỉ định với .split('/', 1), bạn sẽ nhận được một mảng như ['3'], không phải là chuỗi "3" (như tôi nghĩ bạn có thể giả định). Vì vậy:

currentmonth = currentdate.split("/", 1); // currentmonth is ["3"] 
currentmonth == 3; // true, as described above 
opens[i]["date"].split("/", 1) == 3; // true, because left-hand evals to ["3"] 
opens[i]["date"].split("/", 1) == currentmonth; 
// false, because you're comparing two arrays - ["3"] != ["3"] 

Để sửa lỗi này với mã hiện tại của bạn, bạn có thể chỉ nhận được chuỗi, không phải là mảng, như thế này:

currentmonth = currentdate.split("/")[0]; // currentmonth is "3" 
opens[i]["date"].split("/")[0] == currentmonth; // true, both sides are "3" 
+0

Tôi nên kiểm tra phần còn lại của câu trả lời trước khi tiếp tục, tôi chỉ đi đến kết luận tương tự. Câu trả lời tốt. – Nicole

+0

Tôi đã thêm một số [chi tiết của riêng tôi] (http://stackoverflow.com/questions/8056317/javascript-operator-lies/8056914#8056914), nhưng tín dụng đi vào bạn để phát hiện vấn đề mảng đầu tiên. – Nicole

0

Bạn có thể thử điều này chỉ để biết nếu đó là số nguyên so với lỗi chuỗi không?

Đây không phải là một giải pháp tốt đẹp nhưng nó mang lại một đầu mối.

while(opens[i]["date"].split("/", 1) + "str" == currentmonth + "str") 
+1

tôi sẽ sử dụng 'parseInt' để thay thế. –

7

Nhập JavaScript là ẩn. Điều này có nghĩa là nếu nó nghĩ rằng bạn đang cố gắng để đối xử với một cái gì đó như một số, nó sẽ làm tốt nhất để đối xử với đối tượng đó như một số, ngay cả khi nó là, nói, một boolean, hoặc một chuỗi.

Khi thực hiện tiêu chuẩn ==, JavaScript sẽ sử dụng chuyển đổi ẩn để thử và so khớp các loại. Điều này thường dẫn đến kết quả so sánh không mong muốn.

Nếu bạn muốn ép buộc so sánh mạnh, bạn phải sử dụng toán tử ===.

Điều đó đang được nói, nếu bạn đang kiểm tra đại diện 'số' của một chuỗi, ví dụ: "123" và muốn sử dụng các so sánh mạnh, bạn phải chuyển đổi nó thành một số bằng cách sử dụng parseInt (str, 10);

Để biết một số ví dụ về cách nhập nội dung ẩn, hãy xem câu trả lời JavaScript truth table.

+0

Câu trả lời hay, nhưng không thực sự giải thích nguyên nhân của vấn đề, chỉ là thực hành tốt nhất. – nrabinowitz

+0

'Số' [hàm tạo được gọi là hàm] (http://stackoverflow.com/questions/2381399/what-is-the-difference-between-new-number-and-number-in-javascript/2381580#2381580) cũng hoạt động. – Nicole

1

Hãy upvote nrabinowitz's answer vì ông là đầu tiên và nó là đúng.

Tuy nhiên, tôi muốn thêm một số chi tiết về vấn đề cơ bản và cách Javascript xử lý == chuyển đổi ngầm giữa Mảng, Số và Chuỗi.

Để tóm tắt: Mỗi loại có các quy tắc hơi khác nhau khi sử dụng == với các loại khác nhau. Mảng được chuyển đổi thành giá trị nguyên thủy khi so sánh với Số hoặc Chuỗi, nhưng không được so sánh với một Mảng khác.

chi tiết:

  1. String.split trả về một mảng.
  2. Chuỗi và số là nguyên types trong Javascript. Những người khác là Boolean, Object, Null, và Undefined.
  3. Mảng là gõ Object
  4. == theo "Abstract equality comparison algorithm" (x == y)
  5. Trong hai so sánh đầu tiên bạn, kể từ khi một trong những loại (3) là một số, tình trạng của bạn thuộc quy tắc sau:

    Nếu Type (x) là một trong hai Chuỗi hoặc Số và Type (y) là Object, trả về kết quả của phép so sánh x == ToPrimitive (y).

    Nói cách khác, nó chuyển đổi các mảng ["3"]-3 và so sánh nó với 3 — đúng (xem docs on ToPrimitive)

  6. Trong trường hợp cuối cùng mà bạn nói là chia, nó rơi theo quy tắc đầu tiên, ("Loại (x) giống với Kiểu (y)" — chúng đều là Đối tượng. Sau đó, nó đánh giá quy tắc sau:

    Trả về true nếu x và y tham chiếu đến cùng một đối tượng. Nếu không, trả về false.

  7. Chúng chứa các giá trị như nhau, nhưng không giống nhau đối tượng (từng là một khác nhau kết quả của một cuộc gọi đến String.split), do đó kết quả là sai.

Để minh họa:

console.log("3 == [3]?", 3 == [3]); // true 
console.log("3 == ['3']?", 3 == ['3']); // true 
console.log("'3' == [3]?", "3" == [3]); // true 
console.log("'3' == ['3']?", '3' == ['3']); // true 
console.log("[3] == [3]?", [3] == [3]); // false 
console.log("['3'] == ['3']?", ['3'] == ['3']); // false - NOT SAME OBJECT 

var a = ['3']; 
var b = a; // SAME OBJECT 

console.log("a == b?", a == b); // true! 

Các giải pháp, như @nrabinowitz nói, là chỉ cần thêm [0] đến cuối cuộc gọi chia để giá trị là yếu tố đầu tiên (một String) thay vì Bản thân mảng.

+0

Chi tiết tốt và cảm ơn đề xuất nâng cao! – nrabinowitz