使用不带 eval 的字符串键访问或创建嵌套的 JavaScript 对象 [英] Accessing or creating nested JavaScript objects with string key without eval

查看:17
本文介绍了使用不带 eval 的字符串键访问或创建嵌套的 JavaScript 对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一个很好的解决方案来通过字符串值访问一个属性,但如果该属性不存在,它应该创建它.如果根结构已经定义了结构的某些部分,则不应覆盖属性,而是合并.

I am looking for a nice solution to access a property by string value, but if the property does not exist it should create it. If the root structure already has defined some parts of the structure, the attributes should not be overwritten, but merged instead.

例如,如果您有一个空对象 test 并且您想在不使用 eval 的情况下设置深层结构.例如

For example if you have an empty object test and you want to set a deep structure without using eval. e.g.

test = {}
test.foo.name = "Hallo" // <<- foo is an Object
test.foo[3] = "Test" // <<- foo should remain as Object, not as Array 
test.foo.data[3].bar = 100 // <<- should not overwrite test.foo.name

我写了一个实际可行的解决方案,但我猜是很糟糕的代码:

I have written a solution that actually works, but it is quite bad code, I guess:

也可用作 jsfiddle:https://jsfiddle.net/gvaLzqqf/4/>

Also available as jsfiddle: https://jsfiddle.net/gvaLzqqf/4/

Object.setValue = function(node, flatKey, value) {
    flatKey = flatKey.replace("[", ".");
    flatKey = flatKey.replace("]", "");
    var parts = flatKey.split(".")
    var oldNode = node
    parts.forEach(function(key, index) {
      if (/^+?(0|[1-9]d*)$/.test(key)) {
        key = key * 1
        if (index > 0) {
          var oldValue = parts[index - 1]
          if (!Array.isArray(oldNode[oldValue])) {
            oldNode[oldValue] = []
            node = oldNode[oldValue]
          }
        }
      }
      if (node[key] == undefined) {
        node[key] = {}
      }
      oldNode = node
      node = node[key]
    }); // for each
    oldNode[parts[parts.length - 1]] = value
    return oldNode[parts[parts.length - 1]]
  } // function

var test = {}
Object.setValue(test, "foo.name", "Mr. Foo")
Object.setValue(test, "foo.data[0].bar", 100)
Object.setValue(test, "and.another[2].deep", 20)

console.log("test = " + JSON.stringify(test))
console.log("test.foo.data[0].bar = " + test.foo.data[0].bar)

那么,有没有更好的方法来实现这一目标?

How ever, is there any better way to achieve this?

推荐答案

您可以通过遍历给定的对象来分割路径并减少路径.如果不存在 Object,则使用名称或数组创建一个新属性.稍后赋值.

You could split the path and reduce the path by walking the given object. If no Object exist, create a new property with the name, or an array. Later assign the value.

function setValue(object, path, value) {
    var way = path.replace(/[/g, '.').replace(/]/g, '').split('.'),
        last = way.pop();

    way.reduce(function (o, k, i, kk) {
        return o[k] = o[k] || (isFinite(i + 1 in kk ? kk[i + 1] : last) ? [] : {});
    }, object)[last] = value;
}

var test = {};
setValue(test, "foo.name", "Mr. Foo");
setValue(test, "foo.data[0].bar", 100);
setValue(test, "and.another[2].deep", 20);
console.log(test);

这篇关于使用不带 eval 的字符串键访问或创建嵌套的 JavaScript 对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆