动态设置嵌套对象的属性

我有一个对象,它可以是任意多个级别的深度,并且可以具有任何现有属性。例如:


var obj = {

    db: {

        mongodb: {

            host: 'localhost'

        }

    }

};

在此我想设置(或覆盖)属性,如下所示:


set('db.mongodb.user', 'root');

// or:

set('foo.bar', 'baz');

属性字符串可以具有任何深度,并且值可以是任何类型/事物。

如果属性键已经存在,则不需要合并对象和数组作为值。


前面的示例将产生以下对象:


var obj = {

    db: {

        mongodb: {

            host: 'localhost',

            user: 'root'

        }

    },

    foo: {

        bar: baz

    }

};

如何实现这种功能?


富国沪深
浏览 457回答 3
3回答

慕村225694

使用您指定的参数,此函数应添加/更新obj容器中的数据。请注意,您需要跟踪obj架构中的哪些元素是容器,哪些是值(字符串,整数等),否则您将开始引发异常。obj = {};&nbsp; // global objectfunction set(path, value) {&nbsp; &nbsp; var schema = obj;&nbsp; // a moving reference to internal objects within obj&nbsp; &nbsp; var pList = path.split('.');&nbsp; &nbsp; var len = pList.length;&nbsp; &nbsp; for(var i = 0; i < len-1; i++) {&nbsp; &nbsp; &nbsp; &nbsp; var elem = pList[i];&nbsp; &nbsp; &nbsp; &nbsp; if( !schema[elem] ) schema[elem] = {}&nbsp; &nbsp; &nbsp; &nbsp; schema = schema[elem];&nbsp; &nbsp; }&nbsp; &nbsp; schema[pList[len-1]] = value;}set('mongo.db.user', 'root');

叮当猫咪

有点晚了,但这是一个非图书馆的,更简单的答案:/**&nbsp;* Dynamically sets a deeply nested value in an object.&nbsp;* Optionally "bores" a path to it if its undefined.&nbsp;* @function&nbsp;* @param {!object} obj&nbsp; - The object which contains the value you want to change/set.&nbsp;* @param {!array} path&nbsp; - The array representation of path to the value you want to change/set.&nbsp;* @param {!mixed} value - The value you want to set it to.&nbsp;* @param {boolean} setrecursively - If true, will set value of non-existing path as well.&nbsp;*/function setDeep(obj, path, value, setrecursively = false) {&nbsp; &nbsp; let level = 0;&nbsp; &nbsp; path.reduce((a, b)=>{&nbsp; &nbsp; &nbsp; &nbsp; level++;&nbsp; &nbsp; &nbsp; &nbsp; if (setrecursively && typeof a[b] === "undefined" && level !== path.length){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; a[b] = {};&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return a[b];&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if (level === path.length){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; a[b] = value;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return value;&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return a[b];&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }, obj);}我做的这个功能可以完全满足您的需求。假设我们要更改深嵌套在此对象中的目标值:let myObj = {&nbsp; &nbsp; level1: {&nbsp; &nbsp; &nbsp; &nbsp; level2: {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;target: 1&nbsp; &nbsp; &nbsp; &nbsp;}&nbsp; &nbsp; }}因此,我们将这样调用函数:setDeep(myObj, ["level1", "level2", "target1"], 3);将导致:myObj = {级别1:{级别2:{目标:3}}}将set递归设置为true将设置对象(如果不存在)。setDeep(myObj, ["new", "path", "target"], 3);将导致:obj = myObj = {&nbsp; &nbsp; new: {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;path: {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;target: 3&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}&nbsp; &nbsp; },&nbsp; &nbsp; level1: {&nbsp; &nbsp; &nbsp; &nbsp; level2: {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;target: 3&nbsp; &nbsp; &nbsp; &nbsp;}&nbsp; &nbsp; }}

蝴蝶刀刀

受其他伙伴的启发:function leaf(obj, path, value) {  const pList = path.split('.');  const key = pList.pop();  const pointer = pList.reduce((accumulator, currentValue) => {    if (accumulator[currentValue] === undefined) accumulator[currentValue] = {};    return accumulator[currentValue];  }, obj);  pointer[key] = value;  return obj;}例:const obj = {  boats: {    m1: 'lady blue'  }};leaf(obj, 'boats.m1', 'lady blue II');leaf(obj, 'boats.m2', 'lady bird');console.log(obj); // { boats: { m1: 'lady blue II', m2: 'lady bird' } }
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript