我有一个包含对象的数组。
大概长这样:
var arr = new Array(
{x:1, y:2},
{x:3, y:4}
);
当我尝试执行以下操作:
arr.indexOf({x:1, y:2});
它返回-1
。
如果我有字符串或数字或其他类型的元素,但不是对象,则 indexOf()
运行良好。
有人知道为什么以及我应该如何搜索数组中的对象元素吗?
当然,我是指除了为对象创建字符串哈希键并将其放入数组之外的方法...
我有一个包含对象的数组。
大概长这样:
var arr = new Array(
{x:1, y:2},
{x:3, y:4}
);
当我尝试执行以下操作:
arr.indexOf({x:1, y:2});
它返回-1
。
如果我有字符串或数字或其他类型的元素,但不是对象,则 indexOf()
运行良好。
有人知道为什么以及我应该如何搜索数组中的对象元素吗?
当然,我是指除了为对象创建字符串哈希键并将其放入数组之外的方法...
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;
}
没有人提到内置函数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
如前所述,两个对象永远不会相等,但如果它们指向同一个对象,则引用可以相等,因此为了让代码做你想要的事情:
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);
}
}
return -1;
}
- JiblaArray.prototpye
上添加可枚举属性的ES5功能的普及。使用带有数字索引的普通for
循环,然后您只需返回i
,而无需将其转换为数字。 - RobG这可以在没有自定义代码的情况下工作
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
注意:这并不提供实际的索引,它只会告诉你你的对象是否存在于当前数据结构中。
这些对象不相等。
您必须实现自己的函数。
例如,您可以这样做:
var index = -1;
arr.forEach(function(v, i) {
if (this.x==v.x && this.y==v.y) index=i;
}, searched);
其中searched
是您的对象之一(或不是)。
(我会用简单的循环来实现它,但使用foreach更美观)
===
),而 indexOf
使用 ===
。(它们也不相等于 ==
。)var a = {x:1, y:2};
var b = {x:1, y:2};
console.log(a === b);
===
和==
用于测试它们的操作数是否引用相同的对象,而不是引用等效的对象(具有相同原型和属性的对象)。
function indexOf(array, val, from, compare) {
if (!compare) {
if (from instanceof Function) {
compare = from;
from = 0;
}
else return array.__origIndexOf(val, from);
}
if (!from) from = 0;
for (var i=from ; i < array.length ; i++) {
if (compare(array[i], val))
return i;
}
return -1;
}
// Save original indexOf to keep the original behaviour
Array.prototype.__origIndexOf = Array.prototype.indexOf;
// Redefine the Array.indexOf to support a compare function.
Array.prototype.indexOf = function(val, from, compare) {
return indexOf(this, val, from, compare);
}
你可以这样使用:
indexOf(arr, {x:1, y:2}, function (a,b) {
return a.x == b.x && a.y == b.y;
});
arr.indexOf({x:1, y:2}, function (a,b) {
return a.x == b.x && a.y == b.y;
});
arr.indexOf({x:1, y:2}, 1, function (a,b) {
return a.x == b.x && a.y == b.y;
});
好处是,如果没有传递比较函数,这仍然会调用原始的indexOf方法。
[1,2,3,4].indexOf(3);
看起来你对这种类型的答案不感兴趣,但对于其他有兴趣的人来说,这是最简单的答案:
var arr = new Array(
{x:1, y:2},
{x:3, y:4}
);
arr.map(function(obj) {
return objStr(obj);
}).indexOf(objStr({x:1, y:2}));
function objStr(obj) {
return "(" + obj.x + ", " + obj.y + ")"
}
objectA === objectB
才成立。 - RobG