Создание ассоциативного массива в Javascript, который имеет пользовательские операции get / put - PullRequest
0 голосов
/ 17 июня 2011

Мне нужно создать Javascript объект, который будет вести себя как ассоциативный массив, но с некоторыми функциями, которые вызываются до получения и установки свойств.

Например, задача может быть такой: мы должны создать объект, который будет содержать значение ключа в квадрате, например:

obj.two should be equal to 4, 
obj.four should be equal to 16, 
obj['twenty one'] should be equal to 441.

Это пример. На самом деле мне нужно сделать настройку операции переопределены тоже. Операции получения и установки отправляются в базу данных, и они не обязательно принимают строки в качестве ключей, а любые типы объектов, из которых он создает запрос к БД.

Как бы я это сделал а) с как можно меньшим количеством сторонних библиотек и б) чтобы он работал на максимально возможном количестве платформ?

Я новичок в JS, я обнаружил, что JS не имеет ассоциативных массивов, полагаясь на возможность определять объекты на лету с произвольными свойствами. Я гуглил и имел идею использовать или даже переопределить lookupgetter (и сеттер), где определить новый метод получения / установки на лету, но я не могу найти, будет ли интерпретатор использовать этот метод каждый раз, когда он встречает новый ключ. В любом случае, похоже, что я не смог бы использовать ничего, кроме строк или, возможно, чисел в качестве ключей.

В Java я бы просто реализовал java.util.Map.

Пожалуйста, помогите мне, как бы я сделал то же самое в Javascript?

редактировать

Я думаю, что получу то, что хочу, если мне удастся переопределить [[Get]] и [[Put]] методы, упомянутые здесь http://interglacial.com/javascript_spec/a-8.html#a-8.6.2.1

Ответы [ 3 ]

2 голосов
/ 17 июня 2011

См. http://ejohn.org/blog/javascript-getters-and-setters/

Также этот конкретный ответ: Javascript геттеры и сеттеры для чайников?

редактировать

Согласно Есть ли в JavaScript эквивалент __getattribute Python __? и Есть ли эквивалент свойства __noSuchMethod__ для свойств или есть способ реализовать его в JS? нет хороший способ выполнить именно то, что хочет ОП. Геттеры и сеттеры бесполезны, потому что вы должны заранее знать название того, что ищете.

Поэтому я рекомендую сделать что-то вроде:

var database = {}
database.cache = {}
database.get = function(key) {
    // INSERT CUSTOM LOGIC to recognize "forty-two"
    if (!(key in database.data))
        database.cache[key] = fetch_data_from_database();
    return database.cache[key];
}
database.put = function(key, value) {
    database.cache[key] = value;
    send_data_to_database(key, value);
}
1 голос
/ 25 августа 2011

Я решил, что самый правильный способ реализовать это - использовать Harmony: Proxies.Он не работает на всех платформах, но позволяет реализовать его наиболее простым способом;и это может быть поддержано в других платформах в будущем.

Эта страница содержит пример, который я использовал в качестве шаблона, чтобы делать то, что я хочу:

http://wiki.ecmascript.org/doku.php?id=harmony:proxies

1 голос
/ 17 июня 2011

Для вашего примера, разве это не делает то, что вы хотите:

var myObj = {};

myObj["two"] = 4;
myObj["four"] = 16;
myObj["twenty one"] = 441;

alert(myObj["four"]); // says 16

Или вы пытаетесь сказать, что объект должен магически вычислять квадраты для вас?

JavaScript объектключи это строкиЕсли вы попытаетесь использовать число в качестве ключа, JavaScript в основном сначала преобразует его в строку.

Сказав это, вы можете использовать объекты в качестве ключей , если определите значащий toString метод для них. Но, конечно, значимый - это то, что происходит в каждом конкретном случае, и только вы будете знать, что нужно сделать для вашего случая.

Вытакже может определять объекты, которые поддерживают свои собственные внутренние структуры данных, к которым вы обращаетесь через методы объекта.Я думаю, что объяснить это выходит за рамки этого поста.Google "шаблон модуля javascript", чтобы начать работу с указателями.

...