【问题标题】:Javascript "==" operator liesJavascript“==”运算符的谎言
【发布时间】:2011-11-08 19:55:34
【问题描述】:

以下内容让我非常困惑。正如 cmets 中所指出的,这些比较似乎可以单独进行,但是放在一起时却不能

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

我已将整个序列与 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")
    }
  }

【问题讨论】:

  • 尝试使用parseInt(stringValue, 10)
  • 如果在// WHY DOESNT THIS WORK 行中使用=== 会发生什么? This answer 暗示 == 是邪恶的,不能被信任。
  • 老实说,我在这里没有看到任何问题。
  • 这与问题无关,但您应该使用setInterval(stepthrough, 250); 而不是setInterval("stepthrough()", 250);
  • 我希望我能投票赞成 @zengr 编辑这个问题的标题,即使在我回答之后我也认为这是一个有争议的陈述(“Javascript 是谎言!谎言!”)

标签: javascript


【解决方案1】:

JavaScript 类型是隐式的。这意味着,如果它认为您正在尝试将某物视为数字,则最好将该对象视为数字,即使它是布尔值或字符串。

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

如果要强制进行强比较,则必须使用 === 运算符。

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

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

【讨论】:

【解决方案2】:

这是问题所在:Javascript 中的["1"] == 1,因为@Matt 描述了隐式转换。但是 Javascript 中的 ["1"] != ["1"],因为您正在比较两个数组,因此是两个对象,并且对象比较仅在它们指向 same 对象时才为真,而不是在它们指向两个相同对象时。

当您使用.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"

【讨论】:

  • 我应该在继续之前检查其余的答案,我只是得出了相同的结论。很好的答案。
  • 我已经添加了一些 details of my own,但是感谢您首先发现了数组问题。
【解决方案3】:

请点赞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) 是 StringNumber 并且 Type(y) 是 Object, 返回比较结果 x == ToPrimitive(y)。

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

  6. 在你说的最后一个被破坏的情况,它属于第一条规则,(“Type(x) is the same as Type(y)”——它们都是Object 。然后它评估以下规则:

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

  7. 它们包含相同的值,但不是相同的对象(每个都是调用String.split不同结果),所以结果是

举例说明:

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] 添加到拆分调用的末尾,以便该值是第一个元素(字符串)而不是数组本身。

【讨论】:

    【解决方案4】:

    你可以试试这个只是为了知道它是否是一个整数与字符串失败?

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

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

    【讨论】:

    • 我会改用parseInt
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-10
    • 1970-01-01
    • 1970-01-01
    • 2013-12-19
    • 2019-12-21
    • 2019-02-11
    相关资源
    最近更新 更多