Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there some way to add meta-data to JavaScript objects?

I would like to add key-value pairs of metadata to arbitrary JavaScript objects. This metadata should not affect code that is not aware of the metadata, that means for example

JSON.stringify(obj) === JSON.stringify(obj.WithMetaData('key', 'value'))

MetaData aware code should be able to retrieve the data by key, i.e.

obj.WithMetaData('key', 'value').GetMetaData('key') === 'value'

Is there any way to do it - in node.js? If so, does it work with builtin types such as String and even Number? (Edit Thinking about it, I don't care about real primitives like numbers, but having that for string instances would be nice).

Some Background: What I'm trying to do is cache values that are derived from an object with the object itself, so that

  • to meta data unaware code, the meta data enriched object will look the same as the original object w/o meta
  • code that needs the derived values can get it out of the meta-data if already cached
  • the cache will get garbage collected alongside the object

Another way would be to store a hash table with the caches somewhere, but you'd never know when the object gets garbage collected. Every object instance would have to be taken care of manually, so that the caches don't leak.

(btw clojure has this feature: http://clojure.org/metadata)

like image 720
Evgeniy Berezovsky Avatar asked Jul 31 '12 13:07

Evgeniy Berezovsky


1 Answers

You can use ECMA5's new object properties API to store properties on objects that will not show up in enumeration but are nonetheless retrievable.

var myObj = {};
myObj.real_property = 'hello';
Object.defineProperty(myObj, 'meta_property', {value: 'some meta value'});
for (var i in myObj)
    alert(i+' = '+myObj[i]); //only one property - @real_property
alert(myObj.meta_property); //"some meta value"

More information here: link

However you're not going to be able to do this on primitive types such as strings or numbers, only on complex types.

[EDIT]

Another approach might be to utilise a data type's prototype to store meta. (Warning, hack ahead). So for strings:

String.prototype.meta = {};
String.prototype.addMeta = function(name, val) { this.meta[name] = val; }
String.prototype.getMeta = function(name) { return this.meta[name]; };
var str = 'some string value';
str.addMeta('meta', 'val');
alert(str.getMeta('meta'));

However this is clearly not ideal. For one thing, if the string was collected or aliased (since simple data types are copied by value, not reference) you would lose this meta. Only the first approach has any mileage in a real-world environment, to be honest.

like image 151
Mitya Avatar answered Sep 28 '22 07:09

Mitya