如何检查Javascript Map是不是有对象键
Posted
技术标签:
【中文标题】如何检查Javascript Map是不是有对象键【英文标题】:How to check if Javascript Map has an object key如何检查Javascript Map是否有对象键 【发布时间】:2017-12-10 22:20:30 【问题描述】:查看几个不同的文档,我只看到 Map (ECMAScript6) 键是布尔值、字符串或整数时。有没有办法我们可以使用另一个自定义对象(使用 new CustomObject(x,y) 构造函数调用)作为键添加?
我可以添加一个对象作为键,但无法检查 Map 是否具有所述对象。
var myMap = new Map();
myMap.set( new Tuple(1,1), "foo");
myMap.set('bar', "foo");
myMap.has(?);
myMap.has('bar'); // returns true
有没有办法解决这个问题?
var myMap = new Map();
myMap.set( new Tuple(1,1), "foo");
for(some conditions)
var localData = new Tuple(1,1); //Use directly if exists in myMap?
map.has(localData) // returns false as this is a different Tuple object. But I need it to return true
https://developer.mozilla.org/en-US/docs/Web/javascript/Reference/Global_Objects/Map/has
【问题讨论】:
是的,您可以使用任何对象作为键。但是,它每次都必须是同一个对象——而不仅仅是一个具有相同键和值的对象。嵌套的Map
是实现Tuple
查找的一种选择。
不幸的是,我无法检查它本身是否是同一个对象。它必须是具有一些设置相同的公共属性的对象。有没有办法做到这一点?
作为一名 Java 程序员,Javascript Map
的这些语义令人惊讶和困惑。在 Java 中,我们必须为我们的类提供 equals()
和 hashCode()
方法,然后 Java HashMap
类在使用不同对象但等效对象的键时按预期工作(即,键可以具有 值语义)。
【参考方案1】:
你只需要保存对对象的引用:
var myMap = new Map();
var myKey = new Tuple(1,1);
myMap.set( myKey, "foo");
myMap.set('bar', "foo");
myMap.has(myKey); // returns true; myKey === myKey
myMap.has(new Tuple(1,1)); // returns false; new Tuple(1,1) !== myKey
myMap.has('bar'); // returns true; 'bar' === 'bar'
编辑:以下是如何使用对象来实现您想要的,即通过对象的值而不是引用来比较对象:
function Tuple (x, y)
this.x = x;
this.y = y;
Tuple.prototype.toString = function ()
return 'Tuple [' + this.x + ',' + this.y + ']';
;
var myObject = ;
myObject[new Tuple(1, 1)] = 'foo';
myObject[new Tuple(1, 2)] = 'bar';
console.log(myObject[new Tuple(1, 1)]); // 'foo'
console.log(myObject[new Tuple(1, 2)]); // 'bar'
这些操作平均会在恒定时间内运行,这比在线性时间内通过 Map 搜索相似的对象键要快得多。
【讨论】:
谢谢。不幸的是,我不能对对象使用相同的 myKey 引用。我正在检查具有相同属性集的对象。有什么办法可以解决这个问题。 @LoserCoder 是的,为您的类创建一个 toString() 方法,该方法为具有相同值的实例生成相同的字符串,然后将这些字符串用作对象中的键(那样你就不用甚至必须使用地图)。这就是地图和对象比较在 JS 中的工作方式——对象通过引用进行比较。 @LoserCoder 我添加了一个例子来说明我的意思。这种方法由您自己决定,以确保您的 toString 方法能够准确地序列化您的值对象以进行比较。仅仅因为两个对象是使用相同的构造函数和参数创建的,并不意味着它们一定是等价的。【参考方案2】:当你给map设置一个对象时,你需要在检查map是否有它的时候传递相同的内存引用。
例子:
const map = new Map();
map.set(new Tuple(1,1));
map.has(new Tuple(1,1)) // False. You are checking a new object, not the same as the one you set.
const myObject = new Tuple(1,1);
map.set(myObject);
map.has(myObject) // True. You are checking the same object.
编辑
如果你真的必须这样做,你可以这样做:
function checkSameObjKey(map, key)
const keys = map.keys();
let anotherKey;
while(anotherKey = keys.next().value)
// YOUR COMPARISON HERE
if (key.id == anotherKey.id) return true;
return false;
const map = new Map();
map.set(id: 1, 1);
checkSameObjKey(map, id: 1); // True
checkSameObjKey(map, id: 2); // False
【讨论】:
是的,但我正在寻找是否有已知的解决方法。或者我根本不应该在这种情况下使用 Set/Map。如果是这样,我可能不得不直接使用对象引用,但这会导致同样的问题。 用可能的解决方法编辑了我的答案。 @LoserCoder 请注意,此方法使用线性查找,其运行速度比使用 JavaScript 引擎内置的对象键解析算法(哈希表)慢得多,平均时间是恒定的。以上是关于如何检查Javascript Map是不是有对象键的主要内容,如果未能解决你的问题,请参考以下文章