美文网首页
==怎么会比===慢15倍呢?

==怎么会比===慢15倍呢?

作者: 涅槃快乐是金 | 来源:发表于2024-04-06 16:06 被阅读0次

    我们都知道JavaScript有==(相等)和===(严格相等)运算符进行比较。但究竟有何区别,更重要的是,在幕后发生了什么?让我们深入了解!

    区别

    ==是一种强制转换比较。这里的强制转换意味着虚拟机(VM)试图强制两侧变成相同的类型,然后再比较它们是否相等。以下是一些被自动强制转换成相等的示例:

    "1" == 1 // true
    1 == "1" // true
    true == 1 // true
    1 == true // true
    [1] == 1 // true
    1 == [1] // true
    

    强制转换是对称的,如果a == btrue,则b == a也是true。另一方面,===只有在两个操作数完全相同(除了 Number.NaN之外)时才为true。因此,以上示例中的任何一个都不会在 ===中为true

    强制转换规则

    实际规则很复杂(这本身就是不使用 ==的原因之一)。但为了展示规则有多复杂,我尝试使用 ===实现了==

    function doubleEqual(a, b) {
      if (typeof a === typeof b) return a === b;
      if (wantsCoercion(a) && isCoercable(b)) {
        b = b.valueOf();
      } else if (wantsCoercion(b) && isCoercable(a)) {
        const temp = a.valueOf();
        a = b;
        b = temp;
      }
      if (a === b) return true;
      switch (typeof a) {
        case "string":
          if (b === true) return a === "1" || a === 1;
          if (b === false) return a === "0" || a === 0 || a == "";
          if (a === "" && b === 0) return true;
          return a === String(b);
        case "boolean":
          if (a === true) return b === 1 || String(b) === "1";
          else return b === false || String(b) === "0" || String(b) === "";
        case "number":
          if (a === 0 && b === false) return true;
          if (a === 1 && b === true) return true;
          return a === Number(String(b));
        case "undefined":
          return b === undefined || b === null;
        case "object":
          if (a === null) return b === null || b === undefined;
        default:
          return false;
      }
    }
    
    function wantsCoercion(value) {
      const type = typeof value;
      return type === "string" || type === "number" || type === "boolean";
    }
    
    function isCoercable(value) {
      return value !== null && typeof value == "object";
    }
    

    哇,这太复杂了,我甚至不确定它是否正确!

    有趣的是,如果操作数之一是对象,虚拟机会调用.valueOf()来允许对象强制转换为原始类型。

    强制转换的性能成本

    好吧,那个实现很复杂。那么=====慢多少?看看这个图表。 (查看此处的基准测试)

    首先让我们谈谈数字数组。当虚拟机注意到数组是纯整数时,它会将它们存储在一个称为 PACKED_SMI_ELEMENTS的特殊数组中。在这种情况下,虚拟机知道可以将 ==视为===,性能是一样的。这解释了为什么在数字的情况下=====没有区别。但一旦数组包含除了数字以外的东西,对于 ==来说情况就开始变得糟糕了。

    对于字符串,== 的性能降低了 50%,而且只会变得更糟。

    字符串在虚拟机中是特殊的,但一旦涉及到对象,我们就会慢 4 倍。看看混合列,减速现在是 4 倍!

    但情况变得更糟。对象可以定义 valueOf来将自身强制转换为原始值。所以现在虚拟机必须调用该方法。当然,定位对象上的属性是受内联缓存控制的。内联缓存是属性读取的快速路径,但是一个多态读取可能会体验到 60 倍的减速,这可能会使情况变得更糟。如图所示,作为最坏情况(objectsMega)的情况下,=====慢 15 倍!

    继续使用 == 的理由?

    现在,===非常快!因此,即使使用==将速度降低15倍,在大多数应用程序中也不会产生太大的影响。然而,我很难想出为什么应该使用==而不是===的任何理由。强制转换规则很复杂,而且它是性能上的一大障碍,所以在使用==之前请三思。

    相关文章

      网友评论

          本文标题:==怎么会比===慢15倍呢?

          本文链接:https://www.haomeiwen.com/subject/tmnatjtx.html