我需要确定一个对象是否已经存在于javascript数组中。

如(dummycode):

var carBrands = [];

var car1 = {name:'ford'};
var car2 = {name:'lexus'};
var car3 = {name:'maserati'};
var car4 = {name:'ford'};

carBrands.push(car1);
carBrands.push(car2);
carBrands.push(car3);
carBrands.push(car4);

现在“carBrands”数组包含了所有实例。 我现在正在寻找一个快速的解决方案来检查car1, car2, car3或car4的实例是否已经在carBrands数组中。

eg:

var contains =  carBrands.Contains(car1); //<--- returns bool.

Car1和car4包含相同的数据,但它们是不同的实例,应该测试为不相等。

我是否需要在创建对象时添加散列之类的东西?或者在Javascript中有更快的方法来做到这一点。

我在这里寻找最快的解决方案,如果肮脏,所以它必须是;)在我的应用程序中,它必须处理大约10000个实例。

没有jquery


当前回答

最近被FP bug咬了一口,阅读了许多关于函数式范式如何与Javascript完美契合的精彩描述

为了完整起见,我复制了代码,并提出了两种可以实现此功能的方法。

    var carBrands = [];

  var car1 = {name:'ford'};
  var car2 = {name:'lexus'};
  var car3 = {name:'maserati'};
  var car4 = {name:'ford'};
  var car5 = {name:'toyota'};

  carBrands.push(car1);
  carBrands.push(car2);
  carBrands.push(car3);
  carBrands.push(car4);

  // ES6 approach which uses the includes method (Chrome47+, Firefox43+)

  carBrands.includes(car1) // -> true
  carBrands.includes(car5) // -> false

如果你需要支持旧的浏览器使用polyfill,似乎IE9+和Edge不支持它。位于MSDN页面的填充部分

或者,我想对cdhowie提出一个更新的答案

// ES2015 syntax
function containsObject(obj, list) {

    return list.some(function(elem) {
      return elem === obj
    })
}

// or ES6+ syntax with cool fat arrows
function containsObject(obj, list) {

    return list.some(elem => elem === obj)
}

其他回答

你可以尝试基于属性对数组进行排序,如下所示:

carBrands = carBrands.sort(function(x,y){
  return (x == y) ? 0 : (x > y) ? 1 : -1;
});

然后您可以使用迭代例程来检查是否

carBrands[Math.floor(carBrands.length/2)] 
// change carBrands.length to a var that keeps 
// getting divided by 2 until result is the target 
// or no valid target exists

大于或小于目标,等等,这将让您快速遍历数组以查找对象是否存在。

你可以使用jQuery的grep方法:

$.grep(carBrands, function(obj) { return obj.name == "ford"; });

但由于没有指定jQuery,可以只对函数求导。从源代码:

function grepArray( elems, callback, inv ) {  
    var ret = [];  

    // Go through the array, only saving the items  
    // that pass the validator function  
    for ( var i = 0, length = elems.length; i < length; i++ ) {  
        if ( !inv !== !callback( elems[ i ], i ) ) {  
            ret.push( elems[ i ] );  
        }  
    }  

    return ret;  
}  

grepArray(carBrands, function(obj) { return obj.name == "ford"; });

你可以使用Array.find()。

在你的例子中是这样的

carBrands.find(function(car){
    let result  = car.name === 'ford'
    if (result == null){
        return false;
    } else {
        return true
    }
});

如果car不为空,它将返回包含字符串'ford'的javaScript对象

为什么不使用javascript数组的indexOf方法呢?

看看这个:MDN indexOf Arrays

只是做的事:

carBrands.indexOf(car1);

它将返回car1的索引(在数组中的位置)。如果在数组中没有找到car1,它将返回-1。

http://jsfiddle.net/Fraximus/r154cd9o

Edit: Note that in the question, the requirements are to check for the same object referenced in the array, and NOT a new object. Even if the new object is identical in content to the object in the array, it is still a different object. As mentioned in the comments, objects are passed by reference in JS and the same object can exist multiple times in multiple structures. If you want to create a new object and check if the array contains objects identical to your new one, this answer won't work (Julien's fiddle below), if you want to check for that same object's existence in the array, then this answer will work. Check out the fiddles here and in the comments.

我将在数组上使用属性/值的泛型迭代器。不需要jQuery。

arr = [{prop1: 'val1', prop2: 'val2'}, {prop1: 'val3', prop2: 'val4'}];

objectPropInArray(arr, 'prop1', 'val3'); // <-- returns true

function objectPropInArray(list, prop, val) {
  if (list.length > 0 ) {
    for (i in list) {
      if (list[i][prop] === val) {
        return true;
      }
    }
  }
  return false;  
}