4

我的任务

在我的 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 和 setter,我正在搜索的是类似于Default GetterDefault Setter的东西。所以我可以将排序后的地图隐藏在对象接口后面。

  • 在您知道的任何框架中是否已经有解决方案?
  • 有没有像“默认getter/setter”这样的机制?
4

5 回答 5

6

恐怕你需要在内部使用数组的某种包装器。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?

于 2013-02-01T11:38:51.660 回答
5

添加指向提供排序地图和其他实现的自定义 javascript 库的链接,以供将来在此线程中参考。查看https://github.com/monmohan/dsjslib -msingh

于 2013-08-27T06:00:41.180 回答
3

我不知道通用解决方案,但非通用解决方案的构造非常简单。

通常,您维护一个对象数组,其中几个方法被定义为数组的属性。至少,这是我的方法。

这是一个示例,取自一个更大的应用程序(以修改后的形式):

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 用于查找一个 Array 用于 order。小心,两者可以保持完全的完整性。

于 2013-02-01T12:22:23.533 回答
0

请参阅我对这个问题的回答。我实现了一个基本的有序哈希表(仅限 ES 5+,不需要填充)

于 2014-07-03T18:06:21.627 回答
-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 方法将始终采用键值对,在内部使用实际映射的排序键创建另一个映射,更新值并返回具有排序键的更新映射。无需包含外部库。

于 2017-01-15T14:53:43.160 回答