0

我很惊讶在 StackOverflow 上找不到这个问题的答案(也许我搜索的不正确)。

但基本上我很想知道是否有类似于 Array.indexOf() 方法的东西,但对于对象。也就是说,一种返回现有对象中值的索引的有效方法。

例如,假设我有一个对象:

var obj = { prop1: "a", prop2: "b", prop3: "c", prop4: "a" };

现在我想找到包含“a”的索引,最好做 aobj.indexOf("a")并让它返回类似的东西["prop1", "prop4"]

但这似乎不是对象的实现方法。

或者,我知道我可以创建一个函数:

function indexOf(val, obj){
  var indexes = [];

  for (var index in obj){
      if(!obj.hasOwnProperty(index)) continue;

      if(obj[index] == val){
        indexes.push(index);
      }   
   }

   if(!indexes.length) return false;
   else return indexes;
}

indexOf("a", obj); // returns ["prop1","prop4"]

但是以这种方式迭代整个对象感觉很笨拙!我将要处理的一些对象会非常大,而且值也可能非常大。

有没有更好、更有效的方法?

4

1 回答 1

1

如果你有一个非常大的对象,你可以使用一个复杂的 O(1) 的弱映射实现 来存储每个对象的键。因此,您必须实现您的哈希集合,因此在设置键值对时,您还将键存储在弱映射中。我还做了一些板凳。此自定义 HashMap 与 RawObject 搜索的比较 - jsperf

function HashMap() {
    this.__map = new WeakMap;
    this.__hash = {};
}

HashMap.prototype = {
    set: function(key, value){
        this.unset(key);

        if (value == null) 
            return;

        this.__hash[key] = value;

        var keys = this.__map.get(value);
        if (keys == null) 
            this.__map.set(value, keys = []);

        keys.push(key);
    },
    unset: function(key){
        var value = this.__hash[key];
        if (value) {

            var keys = this.__map.get(value),
                index = keys.indexOf(key);

            keys.splice(index, 1);
        }
        this.__hash[key] = void 0;
    },

    get: function(key){
        return this.__hash[key];
    },
    getKeys: function(value){
        return this.__map.get(value);
    }
};

WeakMapObject.defineProperty在其核心中使用方法。出于这个原因,有一些限制:

  • 浏览器:IE9+
  • 上面 HashMap 示例中的对象作为值,因为它们在 WeakMap 集合中用作键

但是这种方法极大地提高了性能,因为不需要遍历对象来寻找特定的值。

于 2013-11-09T00:35:13.870 回答