如何实现类似 lodash.get 函数?

实现一个类似于 Lodash.get 的函数,该函数用于安全地访问嵌套对象的属性值,并提供默认值。

JavaScript 中等 Lodash 嵌套对象 函数

lodash.get函数的作用是通过路径安全地访问嵌套对象的属性值,避免因路径节点不存在(如undefined或null)而抛出错误,并提供默认值作为后备。它在处理对象结构不确定的场景时特别实用。语法为get(object, path, defaultValue),其中object是目标对象,path可以是字符串(如a.b.c)或数组(如['a','b','c']),defaultValue是可选的备用返回值。

实现步骤核心要点如下

  1. 参数验证
    • 首先检查object是否为null或非对象类型(非object类型),若是直接返回defaultValue。因为lodash.get仅能操作对象结构。
  2. 路径标准化
    • 处理path参数支持字符串和数组:若path为字符串,使用正则表达式替换处理方括号索引(例如a转化为a.0),再以点为分隔符分割为键数组(如a.0.b转为['a','0','b'])。
  3. 安全遍历取值
    • 基于标准化路径数组使用循环或reduce迭代器依次访问对象属性:
      • 每一步检查当前对象是否可访问(是否为对象且非null)。
      • 若某节点不可用,中断遍历并设置值为undefined
  4. 返回结果
    • 若最终结果为undefined(代表路径无效或值未定义),返回defaultValue;否则返回解析到的值。

完整实现代码(简化代码清晰度):

function customGet(object, path, defaultValue) {
  // 第1步:验证输入对象是否可操作
  if (object === null || typeof object !== 'object') return defaultValue;
  
  // 第2步:处理path并转为数组结构
  let keyArray = [];
  if (Array.isArray(path)) {
    keyArray = path;
  } else if (typeof path === 'string') {
    // 转换路径 - 移除方括号形成统一点分隔键 (示例 "a.b"->"a.0.b"再分割为数组)
    const normalizedPath = path.replace(/\[(.*?)\]/g, '.$1').replace(/\.{2,}/g, '.');
    keyArray = normalizedPath.split('.').filter(k => k !== '');
  } else {
    return defaultValue; // 不支持path类型
  }
  
  // 第3步:遍历路径取值
  let current = object;
  for (const key of keyArray) {
    if (current !== null && typeof current === 'object') {
      current = current[key];
    } else {
      return defaultValue; // 路径中断,直接返回defaultValue
    }
  }
  
  // 第4步:检查结果返回逻辑
  return current !== undefined ? current : defaultValue;
}

示例使用:

  • 用例1:访问正确路径
    const obj = { a: { b: 10 } };
    const value = customGet(obj, 'a.b', 'default'); // 返回 10
    
  • 用例2:路径未定义时回退到defaultValue
    const undefinedPath = customGet(obj, 'x.y', 'fallback'); // 返回 'fallback'
    
  • 用例3:支持数组路径 (如.get(users, [0,'name'], '')返回用户对象中第一个元素的名称,如果列表为空则返回’’ )。

优化考滤项:

  • 此简化版代码不处理边缘案例如嵌套undefined或被覆盖的prototype属性。
  • 在开发调试时加强路径正则表达式以处理边界字符(如逗号、空字符串)。
  • 实际项目应考虑使用TypeScript增强类型安全和错误防御。