为了账号安全,请及时绑定邮箱和手机立即绑定

动态设置嵌套对象的属性

动态设置嵌套对象的属性

富国沪深 2019-11-13 14:02:42
我有一个对象,它可以是任意多个级别的深度,并且可以具有任何现有属性。例如: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    }};如何实现这种功能?
查看完整描述

3 回答

?
慕村225694

TA贡献1880条经验 获得超4个赞

使用您指定的参数,此函数应添加/更新obj容器中的数据。请注意,您需要跟踪obj架构中的哪些元素是容器,哪些是值(字符串,整数等),否则您将开始引发异常。


obj = {};  // global object


function set(path, value) {

    var schema = obj;  // a moving reference to internal objects within obj

    var pList = path.split('.');

    var len = pList.length;

    for(var i = 0; i < len-1; i++) {

        var elem = pList[i];

        if( !schema[elem] ) schema[elem] = {}

        schema = schema[elem];

    }


    schema[pList[len-1]] = value;

}


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


查看完整回答
反对 回复 2019-11-13
?
叮当猫咪

TA贡献1776条经验 获得超12个赞

有点晚了,但这是一个非图书馆的,更简单的答案:


/**

 * Dynamically sets a deeply nested value in an object.

 * Optionally "bores" a path to it if its undefined.

 * @function

 * @param {!object} obj  - The object which contains the value you want to change/set.

 * @param {!array} path  - The array representation of path to the value you want to change/set.

 * @param {!mixed} value - The value you want to set it to.

 * @param {boolean} setrecursively - If true, will set value of non-existing path as well.

 */

function setDeep(obj, path, value, setrecursively = false) {


    let level = 0;


    path.reduce((a, b)=>{

        level++;


        if (setrecursively && typeof a[b] === "undefined" && level !== path.length){

            a[b] = {};

            return a[b];

        }


        if (level === path.length){

            a[b] = value;

            return value;

        } else {

            return a[b];

        }

    }, obj);

}

我做的这个功能可以完全满足您的需求。


假设我们要更改深嵌套在此对象中的目标值:


let myObj = {

    level1: {

        level2: {

           target: 1

       }

    }

}

因此,我们将这样调用函数:


setDeep(myObj, ["level1", "level2", "target1"], 3);

将导致:


myObj = {级别1:{级别2:{目标:3}}}


将set递归设置为true将设置对象(如果不存在)。


setDeep(myObj, ["new", "path", "target"], 3);

将导致:


obj = myObj = {

    new: {

         path: {

             target: 3

         }

    },

    level1: {

        level2: {

           target: 3

       }

    }

}


查看完整回答
反对 回复 2019-11-13
?
蝴蝶刀刀

TA贡献1801条经验 获得超8个赞

受其他伙伴的启发:


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' } }


查看完整回答
反对 回复 2019-11-13
  • 3 回答
  • 0 关注
  • 456 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信