如何在JavaScript中实现类似MongoDB的点语法动态作用域取值
实现方案
方案1:独立工具函数(兼容性最佳,无副作用)
这种方案不需要修改JS原生对象,兼容所有ES5及以上环境,是生产环境最推荐的写法。
function getNestedValue(obj, path) { // 处理路径首尾多余的点后按点分割为数组 const keys = path.replace(/^\.|\.$/g, '').split('.'); let current = obj; for (const key of keys) { // 中途属性不存在直接返回undefined,避免抛出错误 if (current === null || current === undefined) return undefined; current = current[key]; } return current; }
用法示例
const data = {scope: { to: {nested: "hello"}}}; console.log(getNestedValue(data, "scope.to.nested")); // 输出 "hello"
方案2:Proxy 实现直接data["scope.to.nested"]语法
如果需要完全贴合你提到的访问语法,可以用ES6新增的Proxy代理对象,不会修改Object原型污染全局环境:
// 需要先定义方案1的getNestedValue函数 function createNestedAccessor(obj) { return new Proxy(obj, { get(target, prop) { // 原有正常属性访问逻辑不受影响 if (prop in target) return target[prop]; // 检测到点分隔路径时走嵌套查找逻辑 if (typeof prop === 'string' && prop.includes('.')) { return getNestedValue(target, prop); } return undefined; } }); }
用法示例
const rawData = {scope: { to: {nested: "hello"}}}; const data = createNestedAccessor(rawData); console.log(data["scope.to.nested"]); // 输出 "hello" // 原有链式访问的写法依然可用 console.log(data.scope.to.nested); // 同样输出 "hello"
自定义扩展说明
上述实现默认处理了属性不存在的兼容逻辑,如果需要属性不存在时抛出错误、返回指定默认值,可以自行修改getNestedValue函数的返回逻辑即可。
内容的提问来源于stack exchange,提问作者VolksRat71
相关产品推荐
相关产品推荐

