开发者

Making an associative array in Javascript that has custom get/put operations

I need to make a Javascript object that would behave as an associative array, but with some functions that are called before getting and setting properties.

For example, the task may be like this: we should make an object, that would contain a squared value of a key, like this:

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

This is an example. Actually I need to make setting operation overridden too. The getting and setting operations would go to the database, and they not necceserily would take strings as keys, but any types of objects, from which it would create a DB query.

How would I do that a) with as less thirdparty libraries as possible and b) to make it work on as much platforms as possible?

I am new to JS, I've found that JS has no associative arrays, relying on the ability to define objects on the fly with arbitrary properties. I googled and had an idea to use or even override lookupgetter (and setter), where define a new getter/setter on the fly, but I coundn't find if the interpreter would use this method every time it encounters new key. Anyway, it looks like I wouldn't be able to use anything except strings or maybe numbers as keys.

In Java, I would just implement java.util.Map.

Please help me, how would I do the same in Javascript?

edit

I think I will get what 开发者_开发百科I want if I manage to override [[Get]] and [[Put]] methods mentioned here http://interglacial.com/javascript_spec/a-8.html#a-8.6.2.1


For your example, doesn't this do what you want:

var myObj = {};

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

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

Or are you trying to say that the object should magically calculate the squares for you?

JavaScript object keys are strings. If you try to use a number as a key JavaScript basically converts it to a string first.

Having said that, you can use objects as keys if you define a meaningful toString method on them. But of course meaningful is something that happens on a case by case basis and only you will know what needs to be done for your case.

You can also define objects that maintain their own internal data structures which you access via object methods. I think explaining that is beyond the scope of this post. Google "javascript module pattern" for some pointers to get you started.


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

Also this particular answer: Javascript getters and setters for dummies?

edit

According to Does JavaScript have the equivalent of Python's __getattribute__? and Is there an equivalent of the __noSuchMethod__ feature for properties, or a way to implement it in JS? there is no nice way of accomplishing exactly what the OP wants. Getters and setters are not useful because you must know the name of what you're looking for in advance.

My recommendation would thus be to do something like:

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);
}


I decided that the most correct way to implement this is to use Harmony:Proxies. It isn't working on all platforms, but it lets implement this in the most seamless way; and it may be supported in more platforms in the future.

This page contains an example that I used as a template to do what I want:

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜