My Task
在我的 JavaScript 代码中,我经常使用对象将键"映射"到值,以便以后可以直接通过某个值访问它们。例如:
var helloMap = {};
helloMap.de = "Hallo";
helloMap["en"] = "Hello";
helloMap.es = "Hola";
因此,我使用两种可用的符号对象样式和数组样式在源代码中逐步构建地图对象。
稍后,我可以访问我通过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 中没有找到任何解决方案,给了我这样一个特殊的对象,我遇到了使用 JavaScript 对象中的属性定义 getter 和 setter 的可能性Object.defineProperty
因为我可以依靠 ECMAScript 5 标准,所以我可以使用它。
这个问题的问题是,在实际设置之前,您必须知道可以在对象上设置的所有可能属性。因为如果你定义它,你必须命名它。
我正在寻找的是类似于默认 getter 和 Default Setter 的东西,如果没有为该属性定义 getter 和 setter,则它适用于对象。因此,我可以将排序后的贴图隐藏在对象界面后面。
- 您知道的任何框架中是否已经有解决方案?
- 有没有像"默认获取器/设置器"这样的机制?
恐怕您需要在内部使用数组的某种包装器。ECMAScript 5(这是当前浏览器 JavaScript 实现所基于的标准)根本不允许有序对象属性。
但是,ECMAScript 6 将有一个具有有序属性的Map
实现。另请参阅 http://www.nczonline.net/blog/2012/10/09/ecmascript-6-collections-part-2-maps/。
在 ECMAScript 6 中可能还有其他选项。请参阅以下问题:
如何使用 ECMAScript 5 定义默认的 getter 和 setter?
添加一个指向自定义 javascript 库的链接,该库提供排序映射和其他实现,供将来在此线程中参考。查看 https://github.com/monmohan/dsjslib-姆辛格
通用解决方案,但非通用解决方案的构造非常简单。
通常,您维护一个对象数组,其中多个方法定义为数组的属性。至少,这是我的方法。
下面是一个示例,取自(以修改的形式)来自一个更大的应用程序:
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 对象和一个用于排序的数组。只要小心翼翼,两者可以完全完整地保持。
请参阅我对这个问题的回答。我实现了一个基本的有序哈希表(仅限 ES 5+,没有费心填充)
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 方法将始终采用一个键值对,在内部创建另一个映射,其中包含实际映射中的排序键,更新值并返回带有排序键的更新映射。无需包含外部库。