我很惊讶我在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"]
但是这种感觉很笨拙以这种方式迭代整个对象!我将要处理的一些对象将非常庞大,并且值也可能非常大。
有更好,更有效的方法吗?
答案 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
方法。出于这个原因,存在一些限制:
但是这种方法可以大大提升性能,因为不需要迭代对象,寻找特定的值。