2

考虑以下代码:

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,那么无论何时调用此函数,它都将始终为 true,无论 cacheObj 的值如何。

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

我如何实现我想要的?

4

1 回答 1

4

当你这样做时:

queryParamCache[cacheObj]

你实际上是在这样做:

queryParamCache[String(cacheObj)]

这是(在通用对象上)

queryParamCache["[object Object]"]

不管里面有什么cacheObj

考虑:Live Copy | 直播源

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

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

两者都a变成b了字符串"[object Object]"

我如何实现我想要的?

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

您可以这样做的一种方法是为您的对象提供不同的toString方法,例如:Live Copy | 直播源

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.

或者,当然,您可以toString单独分配给每个对象:Live Copy | 直播源

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]);

...但这就是原型的用途,因此使用原型可能是有意义的,无论是通过构造函数还是Object.create.

于 2013-06-06T07:22:09.133 回答