Как функция Array.prototype.include сравнивает объекты - PullRequest
3 голосов
/ 14 апреля 2020

В спецификациях ECMA мы читаем, что Array.prototype.includes использует SameValueZero алгоритм при сравнении, если массив содержит данный элемент. Этот алгоритм, когда элемент является объектом, использует SameValueNonNumeri c алгоритм, который в основном проверяет соответствие типов сравниваемых элементов и, наконец, в последней точке алгоритма проверяет:

Если x и y - одно и то же значение объекта, вернуть true. В противном случае верните false.

Мой вопрос:

Как алгоритм SameValueNonNumeric выполняет этап сравнения объектов? Как он устанавливает sh, что «x и y - это одно и то же значение объекта»? Я не смог найти это в спецификациях.

Начиная с этого и этого вопроса, кажется, что сравнение объектов не так просто в JS.

Ответы [ 5 ]

3 голосов
/ 14 апреля 2020

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 и проверить все значения объекта

1 голос
/ 14 апреля 2020

Это «одно и то же значение объекта», если они ссылаются на один и тот же блок памяти, если хотите.

Непростые вопросы и ответы, которые вы найдете, все о том, как сравнивать объект содержание осмысленным образом.

Хотя очень просто сравнивать объекты "обычным" способом, то есть сравнивать ссылку, и это то же самое делает includes и здесь. Я согласен, что текст в SameValueNonNumber немного неясен в этот момент, другие алгоритмы указывают это более четко, например, здесь на шаге 1f:

Возвращает true, если x и y относится к тому же объекту . В противном случае верните 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
0 голосов
/ 14 апреля 2020

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]
    },

])
0 голосов
/ 14 апреля 2020

Объекты и символы сравниваются по ссылке.

Мы знаем, что {} === {} или 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));
0 голосов
/ 14 апреля 2020

Я предполагаю, что он использует The Abstract Equality Comparison Algorithm для определения, являются ли значения объекта одинаковыми.

Спецификации для алгоритма здесь .

...