为什么 Array.indexOf 找不到相同的对象

IT技术 javascript arrays search object indexof
2021-01-23 23:52:45

我有对象的数组。

像这样的东西:

var arr = new Array(
  {x:1, y:2},
  {x:3, y:4}
);

当我尝试:

arr.indexOf({x:1, y:2});

它返回-1

如果我有字符串或数字或其他类型的元素但对象,则indexOf()工作正常。

有谁知道为什么以及我应该怎么做来搜索数组中的对象元素?

当然,我的意思是除了为对象制作字符串哈希键并将其赋予数组之外的方法......

6个回答

indexOf 使用严格相等(与 === 或三重相等运算符使用的方法相同)将 searchElement 与 Array 的元素进行比较。

您不能用于===检查对象的平等性。

正如@RobG指出的那样

请注意,根据定义,两个对象永远不会相等,即使它们具有完全相同的属性名称和值。objectA === objectB当且仅当 objectA 和 objectB 引用同一个对象。

您可以简单地编写一个自定义的 indexOf 函数来检查对象。

function myIndexOf(o) {    
    for (var i = 0; i < arr.length; i++) {
        if (arr[i].x == o.x && arr[i].y == o.y) {
            return i;
        }
    }
    return -1;
}

演示: http : //jsfiddle.net/zQtML/

您可以使用===来检查对象的相等性,只是期望当这两个对象是完全不同的文字时它会失败。
2021-03-18 23:52:45
这意味着,我无法比较两个对象是否相同?
2021-03-20 23:52:45
@Jibla 编写一个简单的函数来迭代对象并找到匹配项.. 检查更新的帖子。
2021-03-31 23:52:45
@Vega - 是的,我知道编写自定义函数的最少选择,我只是不想编写自定义函数。PS谢谢!
2021-04-05 23:52:45
@jbaby——两个对象永远不相等,无论你使用=====. 如果被比较的表达式是对象,抽象严格相等比较算法(以及关系算法)都被定义为返回 false。
2021-04-06 23:52:45

如前所述,两个对象永远不会相等,但如果它们指向同一个对象,则引用可以相等,因此要使代码执行您想要的操作:

var a = {x:1, y:2};
var b = {x:3, y:4};
var arr = [a, b];

alert(arr.indexOf(a)); // 0

编辑

这是一个更通用的specialIndexOf函数。请注意,它期望对象的值是基元,否则需要更严格。

function specialIndexOf(arr, value) {
  var a;
  for (var i=0, iLen=arr.length; i<iLen; i++) {
    a = arr[i];

    if (a === value) return i;

    if (typeof a == 'object') {
      if (compareObj(arr[i], value)) {
        return i;
      }
    } else {
      // deal with other types
    }
  }
  return -1;

  // Extremely simple function, expects the values of all 
  // enumerable properties of both objects to be primitives.
  function compareObj(o1, o2, cease) {
    var p;

    if (typeof o1 == 'object' && typeof o2 == 'object') {

      for (p in o1) {
        if (o1[p] != o2[p]) return false; 
      }

      if (cease !== true) {
        compareObj(o2, o1, true);
      }

      return true;
    }
  }
}

var a = new String('fred');
var b = new String('fred');

var arr = [0,1,a];

alert(specialIndexOf(arr, b)); // 2
为什么是两种方式?我写了这样的函数:availableMoves.indexOf = function(obj) { for(i in this) { if (this[i].x == obj.x && this[i].y == obj.y) { return parseInt(i); } } 返回-1; }
2021-03-16 23:52:45
如果您拥有这些属性名称,这将起作用。顺便提一下,不建议在数组上使用 for..in,尤其是在“monkey patch”流行的情况下,用于Array.prototpye添加可枚举属性的 ES5 特性。使用for带有数字索引的普通循环,然后您只需返回即可i,无需将其转换为数字。
2021-03-17 23:52:45
是的,但我动态生成我搜索的对象。谢谢。
2021-03-22 23:52:45
然后您将不得不遍历属性并比较值。您还必须比较两种方式,即 a 是 a,b 是 a。
2021-03-31 23:52:45

由于没有人提到内置函数 Array.prototype.findIndex(),我想提一下它正是作者所需要的。

findIndex() 方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。

var array1 = [5, 12, 8, 130, 44];

function findFirstLargeNumber(element) {
  return element > 13;
}

console.log(array1.findIndex(findFirstLargeNumber));
// expected output: 3

在您的情况下,它将是:

arr.findIndex(function(element) {
 return element.x == 1 && element.y == 2;
});

或者使用 ES6

arr.findIndex( element => element.x == 1 && element.y == 2 );

以上示例的更多信息:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex

最佳答案,无需编写新函数!
2021-04-05 23:52:45

这无需自定义代码即可工作

var arr, a, found;
arr = [{x: 1, y: 2}];
a = {x: 1, y: 2};
found = JSON.stringify(arr).indexOf(JSON.stringify(a)) > - 1;
// found === true

注意:这并没有给出实际的索引,它只告诉你的对象是否存在于当前数据结构中

恭喜,你还是比某些库快。
2021-04-11 23:52:45

这些对象不相等。

您必须实现自己的功能。

你可以这样做,例如:

var index = -1;
arr.forEach(function(v, i) {
   if (this.x==v.x && this.y==v.y) index=i;
}, searched); 

searched你的对象之一在哪里(或不是)。

(我会用一个简单的循环来实现它,但使用 foreach 更漂亮)