基于@dandavis 非常简单的建议,我可以将访问器设置为原型属性。
不eval
Object.prototype
,在枚举usingObject.defineProperty
方面也保持不变。
解决方案实际上是这样的:
function stringContains(string, value)
{ return string.indexOf(value) != -1; }
Object.defineProperty(Object.prototype, "setValueForKey", { value: function(value, key)
{ this[key] = value; }});
Object.defineProperty(Object.prototype, "setValueForKeyPath", { value: function(value, keyPath)
{
if (keyPath == null) return;
if (stringContains(keyPath, '.') == false) { this.setValueForKey(value, keyPath); return; }
var chain = keyPath.split('.');
var firstKey = chain.shift();
var shiftedKeyPath = chain.join('.');
this[firstKey].setValueForKeyPath(value, shiftedKeyPath);
}});
Object.defineProperty(Object.prototype, "getValueForKey", { value: function(key)
{ return this[key]; }});
Object.defineProperty(Object.prototype, "getValueForKeyPath", { value: function(keyPath)
{
if (keyPath == null) return;
if (stringContains(keyPath, '.') == false) { return this.getValueForKey(keyPath); }
var chain = keyPath.split('.');
var firstKey = chain.shift();
var shiftedKeyPath = chain.join('.');
return this[firstKey].getValueForKeyPath(shiftedKeyPath);
}});
测试没问题:
data = {
'name' : 'data',
'first': {
'number': 1,
'text': 'Ya.',
'meta' : {
'lang' : 'en'
}
},
'second': {
'number': 10,
'text': 'Ba.',
'meta' : {
'lang' : 'en'
}
},
'third': {
'number': 100,
'text': 'Da.',
'meta' : {
'lang' : 'hu'
}
}
};
data.setValueForKey('chunk', 'name');
data.setValueForKeyPath('blob', 'name');
var thirdLanguage = data.getValueForKeyPath('third.meta.lang');
data.setValueForKeyPath(thirdLanguage, 'first.meta.lang');
data.setValueForKeyPath(thirdLanguage, 'second.meta.lang');
log(data);
输出与hu
每个数据成员中的语言相同。