Javascript“==”运算符谎言

时间:2011-11-08 19:55:34

标签: javascript

以下让我很困惑。正如评论中所指出的那样,比较似乎是单独工作的,但是当它们放在一起时它们不会

while应该在同一个月的所有日子里运行,然后将i递增1,然后重新开始。

我已经使用console.log完成整个序列以试图解决它,但它没有任何意义。一切似乎彼此相等,但仍未通过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")
    }
  }

4 个答案:

答案 0 :(得分:7)

JavaScript类型是隐含的。这意味着如果它认为你试图将某个东西视为一个数字,那么最好将该对象视为一个数字,即使它是一个布尔值或一个字符串。

在执行标准==时,JavaScript将使用隐式转换来尝试匹配类型。这通常会导致意外的比较结果。

如果您想强制进行强有力的比较,则必须使用===运算符。

话虽如此,如果您正在检查字符串的'数字'表示,例如“123”,并且想要使用强大的比较,您必须使用parseInt(str,10)将其转换为数字;

有关隐式输入操作的一些示例,请参阅JavaScript truth table答案。

答案 1 :(得分:4)

这是问题:Javascript中的["1"] == 1,因为@Matt描述了隐式转换。但是Javascript中的["1"] != ["1"],因为你比较两个数组,因此两个对象和对象比较只有当它们指向相同的对象时才是真的,而不是它们指向两个相同的对象。

当您使用.split('/', 1)进行分配时,您将获得类似['3']的数组,而不是字符串"3"(我认为您可能会假设)。所以:

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"]

要使用当前代码修复此问题,您只需获取字符串,而不是数组:

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

答案 2 :(得分:1)

请upvote nrabinowitz's answer,因为他是第一个,这是正确的。

但是,我确实想要添加一些有关底层问题的详细信息,以及Javascript如何在数组,数字和字符串之间处理==隐式转换。

总结:使用不同类型的==时,每种类型的规则略有不同。与Number或String相比,数组转换为原始值,但与另一个Array比较时则不转换。

<强>详细

  1. String.split返回一个数组。
  2. 字符串和数字在Javascript中是原始types。其他是布尔,对象,空和未定义。
  3. 数组类型为对象
  4. ==跟随“Abstract equality comparison algorithm”(x == y
  5. 在前两次比较中,由于其中一种类型(3)是一个数字,因此您的条件符合以下规则:

      

    如果Type(x)是 String Number 而Type(y)是Object,   返回比较结果x == ToPrimitive(y)。

    换句话说,它将数组["3"]转换为3并将其与3 - true 进行比较(请参阅docs on ToPrimitive

  6. 在你说的最后情况中,它属于第一条规则,(“Type(x)与Type(y)相同” - 它们都是< strong>对象。然后它评估以下规则:

      

    如果x和y引用同一个对象,则返回true。否则,返回false。

  7. 它们包含相同的值,但不是相同的对象(每个是对String.split的调用的不同的结果),因此结果是的即可。
  8. 举例说明:

    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!
    

    正如@nrabinowitz所说,解决方案是简单地将[0]添加到拆分调用的末尾,以便该值是第一个元素(String)而不是Array本身。

答案 3 :(得分:0)

你可以尝试一下,知道它是否是一个整数vs字符串失败?

这不是一个很好的解决方案,但它提供了线索。

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