通过it访问属性';Javascript中的密钥路径?

通过it访问属性';Javascript中的密钥路径?,javascript,object,accessor,kvc,Javascript,Object,Accessor,Kvc,我有 我真的很想访问它,就像: data = { 'first': { 'number': 1, 'text': 'Ya.' }, 'second': { 'number': 10, 'text': 'Da.' } }; 实际上是以更灵活的方式,比如: number = data['first.number']; 是否有任何轻量级库或代码片段可以推荐? 这很酷,但是有点开销。制作一个helpe

我有

我真的很想访问它,就像:

data = 
{
    'first': {
        'number': 1,
        'text': 'Ya.'
    },
    'second': {
        'number': 10,
        'text': 'Da.'
    }
};
实际上是以更灵活的方式,比如:

number = data['first.number'];

是否有任何轻量级库或代码片段可以推荐?
这很酷,但是有点开销。

制作一个helper函数,用于读取可变数量的参数或参数数组

numberOrText = data[memberName+'.'+propertyName];
反规范化代码

data["first"]["number"] == data["first.number"];
data["first.number"] = -1;
data["first"]["number"] != data["first.number"];
基于,我可以将访问器设置为原型属性

eval
,也保留
对象。原型在使用
对象枚举时保持不变。定义属性

解决方案实际上是这样的:

function denormalize(obj, lv) {
    var more = false;
    for(var k in obj) {
        if(k.split(".").length == lv) {
            var node = obj[k]
            if(node && typeof(node) == 'object') {
                more = true;
                for(var k2 in node) {
                    obj[k + "." + k2] = node[k2];
                }
            }
        }
    }
    if(more)
        denormalize(obj, lv + 1);
    return obj;
}

// test it
data = 
{
    'first': {
        'number': 1,
        'text': 'Ya.'
    },
    'second': {
        'number': 10,
        'text': 'Da.'
    },
    "third": [{"number": 5, "text": "meh"},{"number": 6, "text": "beh"}]
};
denormalize(data, 1);
for(var k in data)
    console.log(k + " : " + data[k]);
测试结果良好:

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

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

如果您拥有所有基于点的路径(无数组语法),则可以使用eval或简单的滑动递归函数:

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);
我想你可能会喜欢


您可以使用reduce函数轻松解析密钥路径,而无需使用任何库

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

var foo = {
  bar : {
    name : "Cool!"
  },
  scores : [55, 27, 100, 33]
};

_(foo).valueForKeyPath("bar.name");           // --> "Cool!"
_(foo).setValueForKeyPath("bar.name", "BAR"); // --> sets foo.bar.name as "BAR"
_(foo).valueForKeyPath("scores.@max");        // --> 100
然后,我们定义一个包含keypath字符串的变量keypath:我们希望访问目标对象内的example属性

const target = {
    foo: {
        bar: {
            example: 65
        }
    }
};
艰苦的工作从今天开始!通过点分隔符对密钥路径进行分割,得到密钥数组。我们迭代这个数组(使用reduce函数),每次迭代都返回一个新对象

const keypath = 'foo.bar.example';    ​

最后,结果变量值为65。它起作用了ES2015可以使用解构:

const result = keypath.split('.').reduce((previous, current) => previous[current], target);

我做这件事有点晚了,但我也需要同样的东西,我觉得这件东西小巧实用。(它希望您
拆分('.')
您的.key.path
成为
['your'、'key'、'path']

数据=
{
“第一个”:{
“数字”:1,
“文本”:“是”
},
“第二个”:{
“数字”:10,
“文本”:“Da”,
'array':['a',{'b':'bar'},'c']
}
};
函数值路径(对象,路径){
如果(!object | | path.length==0)返回对象
返回值路径(对象[path.shift()],路径)
}
函数setValueAtPath(对象、路径、值){
如果(!object | | path.length==0)返回null
如果(path.length==1)对象[path[0]=value
else返回setValueAtPath(对象[path.shift()],路径,值)
}
log(valueAtPath(数据,['second','array',1',b']))
setValueAtPath(数据,['second','array',1','b'],'foo')
console.log(data)
有一个简单的方法可以实现这一点

\uuu.get()



数据[memberName][propertyName]
或data.memberName.propertyName有什么问题?如果您的路径没有非wordy字符,您可以计算路径。您还可以使用[].map()或者在分解的路径上循环一步,每次都更深一步,将分支设置为根并继续…@dandavis其中一些将是我的解决方案,谢谢。Eval听起来非常简单。你能发布一个答案来接受吗?@mohkhan:我在DOM元素数据集上存储对控制器对象的引用(数组键路径)。就像数据键路径一样=“viewController.controls.transform.opacitySlider”;然后,只需获取文档的键路径的值,就可以引用该对象。如果我是你,我不会修改object.prototype。如果我修改了,我会使用object.defineProperty()来掩盖它而不是像上面的代码那样保留for循环中断原型属性分配…没错,谢谢你的建议。我也会很快修改答案。修改,现在它是生产安全的。嘿,谢谢你的非评估建议,也是定义属性。现在我得到了最终解决方案,很快就要发布了。我很喜欢,很好的库语法开销对我来说有点太大了。我更喜欢。没问题,我包括了一个解释。优雅的解决方案!你必须为每个入口创建一个键路径。你能解释一下你的意思吗,@FabricioG?
const keypath = 'foo.bar.example';    ​
const result = keypath.split('.').reduce((previous, current) => previous[current], target);
data = 
{
    'first': {
        'number': 1,
        'text': 'Ya.'
    },
    'second': {
        'number': 10,
        'text': 'Da.'
    }
};

const {first:{number: yourValue}} = data;
console.log(yourValue); // 1