假设我定义了几个类。然后我创建每个类的对象。我想将对象保存在由其类键控的地图中,以便我可以根据其类检索对象。
(我使用的是ES6语法,但对于遗留的Javascript,问题可能会保持不变,其中类被函数替换)
// Alternative 1
class Apple {
}
class Banana {
}
let fruitInBag = {};
fruitInBag[Apple] = new Apple();
fruitInBag[Banana] = new Banana();
或者我也可以用相同的结果写下以下内容
// Alternative 2
class Apple {
}
class Banana {
}
const FRUIT_TYPE_APPLE = 1;
const FRUIT_TYPE_BANANA = 2;
let fruitInBag = {};
fruitInBag[FRUIT_TYPE_APPLE] = new Apple();
fruitInBag[FRUIT_TYPE_BANANA] = new Banana();
第二种选择是笨拙的,因为我要定义和维护与类定义分开的常量。所以我更喜欢第一个。但第一种方法效率低下吗? Object
是否足够聪明以有效地实施第一种替代方案?
答案 0 :(得分:1)
Javascript对象中的键始终是字符串。没有整数,也没有函数(类)。为此使用ES6地图!
答案 1 :(得分:-1)
我更新了问题中的代码段,以正确反映问题。完成此操作并从评论和删除的答案中获取建议后,我在Chrome devtools中做了一些分析,如下所示。
从图中可以看出,我以ES6(class Apple
)和ES5(function FnApple
)的方式定义了一个类。然后我将它们保存在常规ES5对象(mapA
)和后来的ES6映射(mapB
)中。在所有情况下,浏览器都会完全对类定义进行字符串化,并将该字符串用作键。这是有效的,因为类的完整字符串化使它与众不同。 (我担心字符串化会转储[Object]
字符串。)
然而,这也意味着使用类或函数对象作为键将使得映射键具有不确定的长度。在实际情况下,当类具有长定义时,密钥可以达到几KB。鉴于此,有意义的是,应该使用独立定义的整数来表示地图中的键。
<强>更新强>
如果是ES6地图,我上面的测试是不正确的。我使用[]
语法将键值赋给了mapB对象,这使得它将键值存储为ES5之类的对象成员(因为即使ES6 Map实例也是一个对象)。在ES6映射上设置键值的正确方法是使用get(),set()API。在这之后,我发现ES6 Map的密钥类型确实是function
而不是String
。