Моя задача

В моем коде 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 с Object.defineProperty, поскольку я могу положиться на ECMAScript 5

Проблема с этим в том, что вы должны знать все возможные свойства, которые могут быть установлены на объекте, прежде чем они будут фактически установлены. Поскольку, если вы определите его, вы получите имя .

То, что я ищу, это что-то вроде Получателя по умолчанию и Установщика по умолчанию , который применяется к объекту, если для свойства не были определены получатель и установщик. Поэтому я мог бы затем скрыть отсортированную карту за интерфейсом объекта.

  • Есть ли решение для этого в каких-либо рамках вы знаете?
  • Есть ли такой механизм, как "getter / setter по умолчанию"?
4
Chris 1 Фев 2013 в 15:11

5 ответов

Лучший ответ

Боюсь, вам понадобится какая-то обертка, использующая массив внутри. ECMAScript 5 (который является стандартом, на котором основаны текущие реализации JavaScript в браузере) просто не допускает упорядоченные свойства объекта.

Однако ECMAScript 6 будет иметь Map реализацию у которого есть упорядоченные свойства. Смотрите также http: // www .nczonline.net / блог / 2012/10 / 09 / ECMAScript -6- коллекции, часть - 2 - карты /.

Также могут быть другие варианты в ECMAScript 6. См. Следующий вопрос:

Как определить метод получения и установки по умолчанию с помощью ECMAScript 5?

6
Community 23 Май 2017 в 12:18

Я не знаю общего решения, но необщее решение очень просто построить.

Как правило, вы поддерживаете массив объектов с несколькими методами, определенными как свойства массива. По крайней мере, это мой подход.

Вот пример, взятый (в измененном виде) из более крупного приложения:

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-объект для поиска и для массива order. С осторожностью, эти два могут поддерживаться с полной целостностью.

3
Beetroot-Beetroot 1 Фев 2013 в 12:34

Посмотрите мой ответ на этот вопрос. Я реализовал базовую упорядоченную хеш-таблицу (только ES 5+, не удосужился заполнить)

0
Community 23 Май 2017 в 10:29

Добавление ссылки на пользовательскую библиотеку JavaScript, которая предоставляет отсортированные карты и другую реализацию, для дальнейшего использования в этой теме. Ознакомьтесь с https://github.com/monmohan/dsjslib -msingh

4
factotum 27 Авг 2013 в 06:00
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 всегда принимает пару ключ-значение, внутренне создает другую карту с отсортированными ключами из фактической карты, обновляет значение и возвращает обновленную карту с отсортированными ключами. Внешнюю библиотеку включать не нужно.

-1
Amit Sharma 16 Янв 2017 в 10:07