我的任务
在我的JavaScript代码中,我经常使用对象将键“映射”到值,以便稍后可以通过某个值直接访问它们。例如:
var helloMap = {};
helloMap.de = "Hallo";
helloMap["en"] = "Hello";
helloMap.es = "Hola";
所以我使用两个可用符号 object style 和 array style 在源代码中逐步构建地图对象。
稍后我可以访问我通过helloMap["de"]
添加的值。如果我不必关心在对象上设置属性的顺序,那就没关系了。
如果我想现在迭代对象属性,据我所知,没有办法确保我按照它们被添加的顺序迭代它们。
注意:我不能使用一些包装器对象,只需在其中保存一个数组,然后使用其方法添加值,如下所示:
var HelloMap = function(){
this.myMap = [];
this.addProperty = function(key, value){
this.myMap.push({key: key, value: value});
}
}
或类似的东西对我不起作用。因此,解决方案需要对使用该对象的程序员绝对透明。
那就是说我需要的对象是一个空对象,它维护了添加到它的属性的顺序。这样的事情可以做到:
var helloMap = {};
helloMap = getOrderAwareObject(helloMap);
以便在“按顺序”对象中跟踪表单helloMap.xy = "foo"
和helloMap["yz"] = "bar"
的每个进一步分配,
可能的解决方案
由于我没有在下划线或jQuery中找到任何解决方案给我这样一个特殊的对象,因此我遇到了使用Object.defineProperty
为JavaScript对象定义属性的getter和setter的可能性,因为我可以依赖 ECMAScript 5 标准我可以使用它。
这个问题是,在实际设置之前,您必须知道可以在对象上设置的所有可能属性。因为如果您定义它,您必须命名它。
我正在搜索的内容类似于默认抓取器和默认设置器,如果没有为该属性定义了getter和setter,它将应用于该对象。所以我可以隐藏对象界面后面的有序地图。
答案 0 :(得分:6)
我担心你需要一个内部使用数组的包装器。 ECMAScript 5(这是当前浏览器JavaScript实现所基于的标准)根本不允许有序对象属性。
但是,ECMAScript 6将具有已订购属性的Map
implementation。另请参阅http://www.nczonline.net/blog/2012/10/09/ecmascript-6-collections-part-2-maps/。
ECMAScript 6中可能还有其他选项。请参阅以下问题:
How can I define a default getter and setter using ECMAScript 5?
答案 1 :(得分:4)
添加指向自定义javascript库的链接,该库提供排序映射和其他实现,以供将来在此线程中引用。查看https://github.com/monmohan/dsjslib -msingh
答案 2 :(得分:3)
我不知道一般解决方案,但非一般解决方案构建起来非常简单。
通常,您维护一个对象Array,其中几个方法被定义为Array的属性。至少,那是我的方法。
以下是一个示例,来自较大的应用程序(以修改的形式):
var srcs = [];
srcs.find = function(dist) {
var i;
for(i=0; i<this.length; i++) {
if(dist <= this[i].dist) { return this[i]; }
}
return null;
};
srcs.add = function(dist, src) {
this.push({ dist:dist, src:src });
}
srcs.remove = function(dist) {
var i;
for(i=0; i<this.length; i++) {
if(this[i].dist === dist) {
srcs.splice(i,1);
return true;
}
}
return false;
};
srcs.add(-1, 'item_0.gif' );
srcs.add(1.7, 'item_1.gif');
srcs.add(5, 'item_2.gif');
srcs.add(15, 'item_3.gif');
srcs.add(90, 'item_4.gif');
不幸的是,你失去了普通js对象查找的简单性,但这是你为拥有一个有序实体付出的代价。
如果你绝对必须有order和dot.notation,那么维护一个普通的js Object用于查找和一个数组用于命令。小心翼翼地保持这两者的完整性。
答案 3 :(得分:0)
请参阅我对this问题的回答。我实现了一个基本的有序哈希表(仅限ES 5+,没有打扰到polyfill)
答案 4 :(得分:-1)
var put = function(k,v){
if(map[k]){
console.log("Key "+ k+" is already present");
}else
{
var newMap = {};
map[k] = v;
Object.keys(map).sort().forEach(function(key){
newMap[key] = map[key];
});
map = newMap;
//delete newMap; in case object memory need to release
return map;
}
}
Put方法将始终采用键值对,在内部创建具有实际地图中的排序键的另一个地图,更新值并使用已排序的键返回更新的地图。不需要包含外部库。