实现Lodash.set 、根据antd的Form.Item组件中的NamePath给对象目标位置赋值

 一、适用范围

传递NamePath,根据NamePath给对象的目标位置赋值,且不会影响对象中其它属性。

模拟:lodash.set | Lodash 中文文档

关于NamePath:antd组件库中的Form.Item属性,可以输入NamePath,会自动填充至对象的目标位置

场景:比如一个对象 obj , 想给对象目标位置赋值,如果你知道这个路径是固定的,那当然可以直接通过点语法 obj.a.b 一步步赋值,但是当需要赋值的路径是动态生成的时候,就不能通过点语法了,需要根据用户传入的路径来进行动态赋值,比如一会想给 obj.a.b赋值,一会想给 obj.c.d[2].e赋值。

二、使用示例

 三、代码及原理

原理已经在下方注释中写的很详细了,主要是利用数组的reduce迭代方法,把指针一步步迭代到目标位置,然后赋值

当path中的路径在obj中存在时,将会直接沿着这条线往下走,当路径不存在时,将会生成新的对象或数组,再继续走下去

/**
 * 根据NamePath,将对象中指定位置的值赋值
 * @param {object} obj 要被操作的对象
 * @param {(string | number)[] | string} path 路径数组
 * @param {*} value 要赋值的数据
 * @returns {object} 返回修改后的对象
 */
const setObjByNamePath = (obj, path, value) => {
    if (Object(obj) !== obj) return obj; // 当传入的obj不是对象时
    // 如果path不是数组,则从字符串路径转数组
    if (!Array.isArray(path)) path = path.toString().match(/[^.[\]]+/g) || [];
    //迭代path,在obj上沿着path一步步往下,找到目标位置,targetPoint是迭代后,目标位置的上一级指针
    let targetPoint = path.slice(0, -1).reduce((lastObj, nowKey, i) => {//slice(0, -1)去掉了最后一个,迭代除最后一个以外的所有内容,每次都返回一个对象/数组的指针给下一个元素调用
        return Object(lastObj[nowKey]) === lastObj[nowKey] // Object(lastObj[nowKey])构造这个键值的对象,如果和原本的不一样说明key不存在
            ? lastObj[nowKey]// 是的话,key存在,那么就把当前的对象继续传递下去
            // 不存在的话,就需要创建这个key,下面判断要新建的是对象还是数组
            : lastObj[nowKey] = Math.abs(path[i + 1]) >> 0 === +path[i + 1] //下一个键是数组索引(数字)的话   注:>> 0是转数字,如果不是纯数字就会变成0, +path[i + 1]也是转数字,但是不是纯数字也可以转
                ? [] //是的话,就新建一个数组,防止下面使用索引报错
                : {}// 否的话,就新建一个对象
    }, obj);//这里的obj是初始值(初始的顶层对象)
    //到最后,把值分配
    targetPoint[path[path.length - 1]] = value; //最后将值分配给最后一个键 
    return obj; //返回修改后的对象的地址,有可能有人操作会用到
};

//测试用例 1   //指定的路径存在时,会直接赋值
let testObj = {
    a:{
        b: []
    },
    ccc: 2
}
setObjByNamePath(testObj , ["a","b", 2] , 666) //在testObj.a.b[2]的位置赋值666
console.log(testObj) 


//测试用例 2   //指定的路径不存在时,会创建这个路径
let testObj2 = {}
setObjByNamePath(testObj2 , ["a",1, "b"] , 777) //在testObj2.a[1].b的位置赋值777
console.log(testObj2) 


猜你喜欢

转载自blog.csdn.net/m0_64130892/article/details/130032696