javascript:检查复杂对象是否在数组中

时间:2013-06-06 07:19:35

标签: javascript

请考虑以下代码:

var queryParamCache = {};

function doThing(filter, offset)
{
  var cacheObj = {filter:filter, offset: offset};

  if (queryParamCache[cacheObj]) {
    //do something
  }
  else{
    queryParamCache[cacheObj] = true;
   //do something else
  }
}

一旦queryParamCache [cacheObj]设置为true,那么每当调用此函数时,无论cacheObj的值如何,它都将始终为true。

我相信它是因为检查是针对[object,object]而不是filter和offset的实际值。

我如何实现我想要的目标?

1 个答案:

答案 0 :(得分:4)

执行此操作时:

queryParamCache[cacheObj]

你实际上是这样做的:

queryParamCache[String(cacheObj)]

(在通用对象上)

queryParamCache["[object Object]"]

无论cacheObj中有什么内容。

考虑:Live Copy | Live Source

var a = {foo: "bar"};
var b = {bar: "charlie"};
var cache = {};

cache[a] = "Hi there";
console.log(cache[b]);  // "Hi there"

ab都会转换为字符串"[object Object]"

  

我如何实现我的目标?

如果您的目标是让queryParamCache成为可以使用对象查找的值的存储,则必须定义将该对象转换为字符串的机制。 JavaScript对象中的属性名称(键)是始终(现在)字符串。

您可以采用的一种方法是为对象提供不同的toString方法,如下所示:Live Copy | Live Source

function CacheEntry(filter, offset) {
  this.filter = filter;
  this.offset = offset;
}
CacheEntry.prototype.toString = function() {
  return "[Cache: " +
    this.filter + "|" +
    this.offset + "]";
};
var a = new CacheEntry("transform", 10);
var b = new CacheEntry("opacity", 22);
var cache = {};

cache[a] = "Hi there";
console.log("cache[a] = " + cache[a]); // "cache[a] = Hi there"
console.log("cache[b] = " + cache[b]); // "cache[b] = undefined"

我已经使用构造函数将原型分配给函数创建的对象,其中该原型替换了toString。构造函数只是分配原型的一种方法;另一个(ES5的新版本,虽然可以填充)是Object.create

当然,您可以单独为每个对象分配toStringLive Copy | Live Source

function cacheEntryToString() {
  return "[Cache: " +
    this.filter + "|" +
    this.offset + "]";
}
var a = {filter: "transform", offset: 10};
a.toString = cacheEntryToString;
var b = {filter: "opacity", offset: 22};
b.toString = cacheEntryToString;
var cache = {};

cache[a] = "Hi there";
console.log("cache[a] = " + cache[a]);
console.log("cache[b] = " + cache[b]);

...但这就是原型 for ,因此通过构造函数或Object.create使用原型可能是有意义的。