Вот машинописный код, который есть у меня в приложении NexJS:
const holeSet:any[] = [];
.....
let xx = 1, yy = 2;
holeSet.push({x:xx,y:yy});
xx = 3;
yy = 4;
holeSet.push({x:xx,y:yy});
holeSet.map((e) => {
console.info("element ::"+JSON.stringify(e));
});
const a = 1;
const b = 2;
if (holeSet.includes({x:a.toString(),y:b.toString()}))
console.info("Value {1;2} FOUND !");
Вот результат, полученный при запуске приведенного выше кода:
элемент ::{"x":1,"y":2} элемент ::{"x":3,"y":4}
Моя проблема в том, что я не знаю, что делаю не так.
Я ожидаю сообщение: Значение {1;2} НАЙДЕНО!
появиться, но этого не происходит. Почему это ?
Я предполагаю, что плохой синтаксис в операторе if ??
Array.prototype.includes использует строгое равенство (===), чтобы проверить, существует ли элемент в массиве. Например: const x = {xx: 1, yy: 2}; const y = {xx: 1, yy: 2}; x !== y, потому что они ссылаются на разные объекты в куче памяти. Итак,holeSet.includes({...}) возвращает false. ИспользуйтеholeSet.map(el => JSON.stringify(el)).includes(JSON.stringify({...})) илиholeSet.some(el => el.xx === a && el.yy == = б) или попробуйте lodash библиотеку утилит для более глубокого сравнения. Обратитесь к этому вопросу
Проблема, с которой вы здесь столкнулись, заключается в том, что при сравнении объектов они сравниваются по ссылке, а не по значению. Таким образом, он пытается проверить, является ли это тем же объектом, которым он никогда не будет. Чтобы преодолеть это, я бы использовал что-то вроде этого:
holeSet.some(e => e.x === a && e.y === b)
Это проверит значения каждого объекта в массиве, и я считаю, что это работает так, как вы ожидаете от включений.
На самом деле это работает как с: «if (holeSet.some((o) => o.x===j && o.y===i))», так и с: «if (holeSet.some((o) => o.x== j && o.y==i))"
Использование синтаксиса литерала объекта создает новый объект. Например, в коде, который вы показали:
holeSet.push({ x: xx, y: yy });
// ^^^^^^^^^^^^^^^^
и
if (holeSet.includes({ x: a.toString(), y: b.toString() }))
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
…они создают новые, уникальные объекты.
Array.prototype.includes() использует равенство одинакового значения и нуля для сравнения первого аргумента, предоставленного каждому элементу массива (в спецификации это называется алгоритмом SameValueZero). При использовании этого алгоритма два уникальных объекта никогда не будут равны друг другу, поэтому… использование синтаксиса литерала объекта для создания значения первого аргумента при вызове holeSeet.includes
всегда будет возвращать false:
holeSet.includes({ x: a.toString(), y: b.toString() })
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Using a unique object for this argument will always return `false`
Вы можете использовать Array.prototype.some(), чтобы определить, имеет ли один из элементов ожидаемую форму, используя функцию, которая сравнивает значения свойств x
и y
с ожидаемыми значениями:
if (holeSet.some((o) => o.x === a && o.y === b))
Код на игровой площадке TypeScript
В результате условие будет оценено как true
, и вы увидите ожидаемое сообщение в консоли.
@jcalz Я искал дубликат, прежде чем ответить , но не нашел. Можете ли вы предоставить URL-адрес представления поискового запроса, который вы использовали для обнаружения того, на который вы ссылались?