在Javascript中使用对象作为键效率低下吗?
假设我定义了几个类。 然后我创建每个类的对象。 我想将这些对象保存在由它们的类键入的地图中,这样我就可以根据它的类来检索该对象。
(我使用的是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
是否足够聪明,可以有效地实现第一种选择?
JavaScript对象中的键总是字符串。 没有整数和没有函数(类)。 使用ES6地图!
我更新了问题中的代码片段以正确反映问题。 做完这些之后,从评论中提出建议并删除答案,我在Chrome devtools中做了如下分析。
从图中你可以看到,我在ES6( class Apple
)和ES5( function FnApple
)方式中定义了一个类。 然后我将它们放在常规的ES5对象( mapA
)和后来的ES6映射( mapB
)中。 在所有情况下,浏览器将类定义完全串联起来并将该字符串用作关键字。 这是有效的,因为类的完整的字符串化使它不同。 (我害怕字符串将转储[Object]
字符串)。
然而,这也意味着使用类或函数对象作为关键字会使得关键字长度不确定。 在现实世界的场景中,当类定义很长时,关键可能会达到几KB。 鉴于此,应该为地图中的键使用独立定义的整数,这是有道理的。
更新
在ES6地图的情况下,我上面的测试是不正确的。 我使用[]
语法将键值赋给mapB对象,这使得它将键值存储为ES5之类的对象的成员(因为即使ES6 Map实例也是一个对象)。 在ES6映射上设置键值的正确方法是使用get(),set()API。 做完这些之后,我发现键的类型确实是function
而不是ES6映射的String
。
上一篇: Is the use of Objects as keys inefficient in Javascript?