使用equivelant Object.indexOf引用Object中Object的索引

时间:2013-11-08 21:46:34

标签: javascript object reference indexof

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

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

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

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

现在我想找到包含“a”的索引,最好做obj.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"]

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

有更好,更有效的方法吗?

1 个答案:

答案 0 :(得分:1)

如果你有一个非常庞大的对象,你可以使用复杂度为O(1)的漂亮weakmap implementation 来存储每个对象的密钥。因此,您必须实现哈希集合,因此在设置键值对时,您还将键存储在weakmap中。 我也做了一些替补。比较此自定义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);
    }
};

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

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

但是这种方法可以大大提升性能,因为不需要迭代对象,寻找特定的值。