【问题标题】:How does the Array.prototype.includes function compare objectsArray.prototype.includes 函数如何比较对象
【发布时间】:2020-04-14 08:53:27
【问题描述】:

在 ECMA 规范中,我们读到 Array.prototype.includes 在比较数组是否包含给定元素时使用 SameValueZero 算法。 这个算法,当元素是一个对象时,它使用SameValueNonNumeric算法,它基本上检查比较元素的类型是否匹配,最后,在算法的最后一点检查:

如果 x 和 y 是相同的 Object 值,则返回 true。否则,返回 false。

我的问题:

SameValueNonNumeric 算法如何执行对象比较步骤?它如何确定“x 和 y 是相同的对象值”?我在规格中找不到这个。

thisthis 的问题看来,JS 中的对象比较并不是那么简单。

【问题讨论】:

  • 基本上是a === b - 他们字面意思是不是同一个对象。
  • 它对每种情况都非常重要。您如何与一般物体进行比较?如果 2 个对象指向同一个实例或者它们具有相同的属性?没有普遍的答案。所以更好的问题应该是你为什么需要它?我觉得比较对象总是表明一种不好的方法。只是我个人的看法。
  • @Aaron 感谢您的评论,我认为您成功了。我想用这个函数来确定文档(对象)列表中是否已经存在具有相同内容的对象。似乎这是一种不好的方法,通过一些唯一的 id 查找对象会更好。最初我认为“包含”会进行如此“深入”的逐个属性比较。
  • 有时你必须听取别人的意见才能重新思考你的设计。很高兴它为您指明了正确的方向:)

标签: javascript arrays javascript-objects


【解决方案1】:

Array.prototype.includes 不应该为您提供正确的对象检查结果,并且设计用于布尔值、字符串和数字值

对于一个对象,它基本上只是做一个引用检查,所以如果对象包含与数组中的引用相同的引用,它会返回 true,否则无论对象中的值如何,它都会返回 false

var arr = [{x: 1, y: 2}, {x: 2, y: 'as'}, {x: 'in', y: 'po'}];
console.log(arr.includes({x: 2, y: 'as'}));
console.log(arr.includes(arr[1]));

为了检查对象是否存在,您需要使用Array.prototype.find 并检查对象的所有值

【讨论】:

  • 布尔、字符串和数字简而言之,原语。
  • 但是布尔、字符串和数字的类型是一个函数而不是原语,你是说布尔、数字和字符串吗?
  • 是的,我的意思是布尔值而不是布尔构造函数
【解决方案2】:

如果它们引用相同的内存块,它们就是“相同的对象值”,如果你愿意的话。

您找到的不简单的问题和答案都是关于如何以有意义的方式比较对象内容

虽然以“常规”方式比较对象非常简单,即比较引用,这也是 includes 在这里所做的。我同意 SameValueNonNumber 中的文字在这一点上有点不清楚,其他算法更清楚地说明了这一点,例如步骤 1f 中的here

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

所以:

const a = { hello: 'world' }
const b = a
const c = { hello: 'world' }

// Now, a and b refer to the same object, but a/b and c do not.

console.log([a].includes(a)) // true
console.log([a].includes(b)) // true
console.log([a].includes(c)) // false

【讨论】:

    【解决方案3】:

    我猜它使用The Abstract Equality Comparison Algorithm 来确定对象值是否相同。

    算法规范here

    【讨论】:

      【解决方案4】:

      对象和符号通过引用进行比较。

      我们知道{} === {}Symbol() === Symbol() 都返回false。快速示例:

      console.log([{}].includes({}));
      console.log([Symbol()].includes(Symbol()));

      如果它们引用相同的“值”,即引用,那么它们将相等:

      const obj = {};
      const sym = Symbol();
      
      console.log([obj].includes(obj));
      console.log([sym].includes(sym));

      【讨论】:

        【解决方案5】:

        Array.prototype.includes 使用=== 运算符进行有效比较。所以对象通过引用进行比较,基元通过值进行比较。

        这是一个比较 includes 结果与 === 结果的示例:

        const object = {'a': 'b'};
        const copyOfObject = JSON.parse(JSON.stringify(object));
        const array = [object, 'a', 1];
        
        console.table([
            {
                'comparison': 'object vs object',
                'result for Array.prototype.includes': array.includes(object),
                'result for === operator': object === array[0]
            },
            {
                'comparison': 'object vs copyOfObject',
                'result for Array.prototype.includes': array.includes(copyOfObject),
                'result for === operator': object === copyOfObject
            },
            {
                'comparison': 'string "a" vs string "a"',
                'result for Array.prototype.includes': array.includes('a'),
                'result for === operator': 'a' === array[1]
            },
            {
                'comparison': 'string "a" vs string "b"',
                'result for Array.prototype.includes': array.includes('b'),
                'result for === operator': 'b' === array[1]
            },
            {
                'comparison': 'number 1 vs number 1',
                'result for Array.prototype.includes': array.includes(1),
                'result for === operator': 1 === array[2]
            },
            {
                'comparison': 'number 1 vs number 2',
                'result for Array.prototype.includes': array.includes(2),
                'result for === operator': 2 === array[2]
            },
        
        ])

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-12-17
          • 1970-01-01
          • 1970-01-01
          • 2019-10-12
          • 1970-01-01
          • 2022-11-21
          • 1970-01-01
          相关资源
          最近更新 更多