如何在不使用eval的情况下通过键数组修改对象深层属性?
安全实现基于键数组的对象属性读取与修改
读取属性(完善版)
先贴一个更健壮的读取实现(和你已有的递归逻辑本质一致,用循环更直观):
function getKeyChain(obj, keys) { let current = obj; for (const key of keys) { // 处理中间路径不存在的情况,避免报错 if (current == null || !(key in current)) { return undefined; } current = current[key]; } return current; }
修改属性(安全替代eval的方案)
核心思路是遍历到倒数第二个键,拿到目标属性的父对象,再直接修改父对象上的目标属性,完全通过原生属性访问操作,没有任何代码注入风险:
function setKeyChain(obj, keys, value) { if (keys.length === 0) return; let current = obj; // 遍历到倒数第二个节点,拿到目标属性的父对象 for (let i = 0; i < keys.length - 1; i++) { const key = keys[i]; // 如果中间路径不存在或不是对象,可选择抛出错误或自动创建嵌套结构 if (current[key] == null || typeof current[key] !== 'object') { throw new Error(`路径 ${keys.slice(0, i+1).join('.')} 不存在或不是对象`); // 若需要自动创建嵌套结构,替换为:current[key] = {}; } current = current[key]; } // 修改最后一个键对应的属性值 current[keys[keys.length - 1]] = value; }
测试示例
const targetObj = {a: {b: {c: 3}}}; const keyPath = ['a','b','c']; // 读取属性 console.log(getKeyChain(targetObj, keyPath)); // 输出 3 // 修改属性 setKeyChain(targetObj, keyPath, 10); console.log(targetObj.a.b.c); // 输出 10
为什么这个方案安全?
全程使用对象的[]属性访问符操作,只会按照键数组的路径访问/修改对象属性,不会执行任何用户输入的代码,完全规避了eval带来的注入风险。
补充:自动创建嵌套结构的版本
如果需要支持给不存在的路径赋值时自动创建嵌套对象,可以用这个变种:
function setKeyChainAutoCreate(obj, keys, value) { let current = obj; for (let i = 0; i < keys.length - 1; i++) { const key = keys[i]; if (current[key] == null || typeof current[key] !== 'object') { current[key] = {}; } current = current[key]; } current[keys[keys.length - 1]] = value; } // 测试 const emptyObj = {}; setKeyChainAutoCreate(emptyObj, ['x','y','z'], 20); console.log(emptyObj.x.y.z); // 输出 20
内容的提问来源于stack exchange,提问作者Serum0017
相关产品推荐
相关产品推荐

