通过它在Javascript中的keyPath访问属性?

Ger*_*eri 3 javascript object accessor kvc

我有

data = 
{
    'first': {
        'number': 1,
        'text': 'Ya.'
    },
    'second': {
        'number': 10,
        'text': 'Da.'
    }
};
Run Code Online (Sandbox Code Playgroud)

我真的想要访问它像:

number = data['first.number'];
Run Code Online (Sandbox Code Playgroud)

实际上以更灵活的方式,如:

numberOrText = data[memberName+'.'+propertyName];
Run Code Online (Sandbox Code Playgroud)

是否有任何轻量级库或您可以建议的代码段?这是 - https://github.com/martinvl/KVCObject - 太酷了,但有点开销.

Thi*_*ier 11

您可以使用reduce函数轻松解析keypath ,而无需使用任何库.

首先,我们创建一个名为target的示例对象,其中包含一些嵌套对象:

const target = {
    foo: {
        bar: {
            example: 65
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

然后,我们定义一个包含keypath字符串的变量keypath:我们想要访问目标对象中的example属性.

const keypath = 'foo.bar.example';    ?
Run Code Online (Sandbox Code Playgroud)

努力工作从今天开始!Keypath被点分隔符拆分,我们获得了一个键数组.我们迭代这个数组(使用reduce函数),并且对于每次迭代,我们返回一个新对象.

const result = keypath.split('.').reduce((previous, current) => {
    return previous[current];
}, target);
Run Code Online (Sandbox Code Playgroud)

最后,结果变量值是65.它的工作原理!

  • 优雅的解决方案! (2认同)

Ger*_*eri 3

基于@dandavis 非常简单的建议,我可以将访问器设置为原型属性。

不,在枚举eval使用Object.prototype方面也保持不变。Object.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);
}});
Run Code Online (Sandbox Code Playgroud)

测试没问题:

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);
Run Code Online (Sandbox Code Playgroud)

hu输出与每个数据成员中的语言相同。