有什么方法可以将元数据添加到JavaScript对象?

我想向任意的JavaScript对象添加元数据的键值对。 这个元数据不应该影响不知道元数据的代码,这就意味着例如

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

元数据感知的代码应该能够通过键检索数据,即

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

有没有办法做到这一点 – 在node.js? 如果是这样,它是否适用于内置types,如String 和偶数 ? ( 编辑思考一下,我不关心像数字这样的真实原语 ,但是对于string实例来说,这样做会很好)。

一些背景:我想要做的是caching从一个对象与对象本身派生的值,以便

  • 到元数据不知道的代码,元数据丰富的对象将看起来与原始对象W / O元相同
  • 如果已经被caching,需要派生值的代码可以从元数据中取出
  • caching将被垃圾收集在对象旁边

另一种方法是将哈希表与高速caching存储在一起,但永远不知道对象何时被垃圾收集。 每个对象实例都必须手工处理,以防止caching泄漏。

(顺便说一句clojure有这个function: http : //clojure.org/metadata )

您可以使用ECMA5的新对象属性API来将对象存储在枚举中不会显示但仍可检索的属性上。

 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" 

更多信息在这里: 链接

然而,你不能在原始types如string或数字上做到这一点,只能在复杂的types上做到这一点。

[编辑]

另一种方法可能是利用数据types的原型来存储元。 (警告,前面的黑客)。 所以对于string:

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

然而这显然不理想。 首先,如果string被收集或别名(因为简单的数据types被复制的价值,而不是引用),你会失去这个元。 说实话,只有第一种方法在现实世界中有任何里程。

ES6规范介绍了Map和WeakMap。 您可以通过运行node --harmony以及在Chrome中启用实验性的JavaScript标志(在默认情况下也是在Firefox中)来启用这些节点。 Maps和WeakMaps允许将对象用作关键字,这些关键字可用于存储关于对象的元数据,这些元数据对于没有访问特定映射/弱映射的任何人都是不可见的。 这是我现在使用很多的模式:

 function createStorage(creator){ creator = creator || Object.create.bind(null, null, {}); var map = new Map; return function storage(o, v){ if (1 in arguments) { map.set(o, v); } else { v = map.get(o); if (v == null) { v = creator(o); map.set(o, v); } } return v; }; } 

使用简单而强大:

 var _ = createStorage(); _(someObject).meta= 'secret'; _(5).meta = [5]; var five = new Number(5); _(five).meta = 'five'; console.log(_(someObject).name); console.log(_(5).meta); console.log(_(five).meta); 

它也促进了一些有趣的用途从接口分离实现:

 var _ = createStorage(function(o){ return new Backing(o) }); function Backing(o){ this.facade = o; } Backing.prototype.doesStuff = function(){ return 'real value'; } function Facade(){ _(this); } Facade.prototype.doSomething = function doSomething(){ return _(this).doesStuff(); } 

您可以将元数据添加为“私有”variables!

 var Obj = function (meta) { var meta = meta; this.getMetaData = function (key) { //do something with the meta object return meta; }; }; var ins_ob = new Obj({meta:'meta'}); var ins_ob2 = new Obj(); if(JSON.stringify(ins_ob) === JSON.stringify(ins_ob2)) { console.log('hoorai'); }; 

JSON中没有“评论”系统。 您可以希望的最好的方式是添加一个不太可能的名称的属性,并添加包含元数据的密钥。 如果知道元数据,则可以读取元数据,但是其他设置只会将其视为另一个属性。 如果有人使用for..in