lodash中的get方法

lodash中使用频率最高的,应该就是_.get()方法去根据路径获取对象的值了。他的使用方式非常简单:

_.get(object, path, [defaultValue])
// 根据 object对象的path路径获取值。 如果解析 value 是 undefined 会以 defaultValue 取代。

这样我们可以使用如:.get(object, ‘a[0].c’, ‘default’); 获取对象n级路径下的值,如果中间路径值为空,返回默认值,以免直接使用a[0].c时因a[0]为undefind造成undefind.c报错。那么lodash中是如何实现.get()方法的呢?

下面 Po 一段 lodash 中 _.get方法的实现(主要功能及解释):

// 1、主方法 get
function get(object, path, defaultValue) {
  // 判断object是否为null,如果不是,调用baseGet方法获取object的path路径下的值
  const result = object == null ? undefined : baseGet(object, path) 
 // 若结果是undefined,则返回默认值
  return result === undefined ? defaultValue : result
}

// 2、baseGet方法 获取对象路径下的值
function baseGet(object, path) {
	// castPath方法获取object的path
  **path = castPath(path, object)**

  let index = 0
  const length = path.length
  
	//如果object不为null且当前index < 路径的长度时,获取object的值,更新object
  **while (object != null && index < length) {
    object = object[toKey(path[index++])] // 将path数组中的值转为key
  }**
	// 最后一级,返回object或者返回 undefined
  return (index && index == length) ? object : undefined
}

// 以上涉及两个方法:(1)将castPath 获取 object中的path,转为数组
// (2)toKey 将path数组中对应的值转为key

// (1)castPath(path, object) 如castPath('a[b].c', object)
function castPath(value, object) {
  if (Array.isArray(value)) {
    return value // 如果value是个数组,直接返回
  }
  return isKey(value, object) ? [value] : stringToPath(value)
	// 其中,isKey方法判断value是不是object对象的获取key的合法路径,主要基于value的类型判断和正则匹配,具体可见[lodash的解释](https://github.com/Liusq-Cindy/lodash/blob/e0029485ab4d97adea0cb34292afb6700309cf16/.internal/isKey.js#L15)
	// stringTopath方法,则是将字符串形式的路径,转化为数组,如将'a[0].c.d' 利用正则和字符串api转化为 ['a',0,'c','d'],具体可见[github](https://github.com/Liusq-Cindy/lodash/blob/e0029485ab4d97adea0cb34292afb6700309cf16/.internal/isKey.js#L15)
}

//(2)toKey(path[index++]) 将path数组中对应的值转为key
const INFINITY = 1 / 0
function toKey(value) {
	// 如果数组中取到的key是字符串或isSymbol为true,则返回字符串
  if (typeof value === 'string' || isSymbol(value)) {
    return value
  }
	// 此外,判断+-0,或者返回value本身,如纯数字 
  const result = `${value}`
  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result
}

以上为lodash中get方式获取path路径下的主流程,更多复杂的如isKey判断和字符串转path数组,可查看github-get.js中具体的实现。

学习及感悟:

1、(1)每一级处理,都需要有判空的判断,避免流程阻断(3)对象获取下一级路径的值时,这里的while方法,要判断新的object是否为null;(3)在获取对象的下一级键值时,使用的是object[key]的方式,这样可以兼容获取a[2]及a[‘b’]这两种形式。

2、学习isKey方法:判断 value 是否是Object的合法路径,并不是简单object[value]就能了事了

const reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/
const reIsPlainProp = /^\w*$/
function isKey(value, object) {
  if (isArray(value)) { // 数组,直接返回false
    return false;
  }
  var type = typeof value; // 对应的几种类型:number,symbol,boolean, null,还有isSymbol判断直接返回true
  if (type == 'number' || type == 'symbol' || type == 'boolean' ||
      value == null || isSymbol(value)) {
    return true;
  }
  return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
    (object != null && value in Object(object));

(1)、reIsPlainProp很好理解,\w 匹配字母或数字或下划线或汉字 等价于 ‘[A-Za-z0-9_]’,*表示0次或多次,即 reIsDeepProp.test(value) 表示value为任意数字及下划线

(2)、value in Object(object) 表示value是object的一个键值

(3)、reIsDeepProp正则表达式,用来匹配属性名里包含路径属性 例如什么. [] \这种

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 你可以使用 JavaScript 的内置函数 `Object.prototype.hasOwnProperty()` 和 `Object.prototype.getOwnPropertyDescriptor()` 来实现类似 lodash 的 `_.get()` 功能。 具体来说,你可以写一个函数,它接受两个参数:对象和路径。函数首先检查路径的每一个属性是否存在于对象,如果存在就继续往下查找,否则返回 `undefined`。 下面是一个示例实现: ``` function get(obj, path) { // 将路径拆分成数组 const pathArr = path.split('.'); // 遍历路径数组 for (const key of pathArr) { // 如果属性不存在或者对象不是一个普通对象,则返回 undefined if (!obj || typeof obj !== 'object') { return undefined; } // 如果属性存在,则将对象更新为该属性的值 if (obj.hasOwnProperty(key)) { obj = obj[key]; } else { return undefined; } } // 返回最终的值 return obj; } ``` 你也可以使用 JavaScript 的内置方法 `Object.prototype.getOwnPropertyDescriptor()` 来获取属性的描述符,并判断它是否是一个 getter。如果是,则调用 getter 函数来获取属性值。 下面是使用 `Object.prototype.getOwnPropertyDescriptor()` 的示例实现: ``` function get(obj, path) { // 将路径拆分成数组 const pathArr = path.split('.'); // 遍历路径数组 for (const key of pathArr) { // ### 回答2: 要实现类似 lodash 的 _.get() 功能,我们可以使用 JavaScript 编程来实现。 _.get() 的功能是根据给定的路径从对象获取对应的值。下面是一个实现该功能的函数: ``` function get(object, path, defaultValue) { // 检查传入的参数是否合法 if (object == null || typeof object !== 'object' || Array.isArray(object)) { return defaultValue; } const keys = path.split('.'); // 将路径拆分成数组 // 遍历路径数组,逐级获取对象的值 let result = object; for (const key of keys) { result = result[key]; if (result == null) { return defaultValue; // 如果某一级的值不存在,则返回默认值 } } return result; } ``` 使用方法示例: ```js const obj = { a: { b: { c: 123, }, }, }; console.log(get(obj, 'a.b.c')); // 输出:123 console.log(get(obj, 'x.y.z', 'default value')); // 输出:default value,因为路径 x.y.z 在对象不存在 ``` 上述代码定义了一个名为 `get` 的函数,它接收三个参数:`object` 表示要获取值的对象,`path` 表示要获取的值的路径,`defaultValue` 表示如果路径不存在时返回的默认值。 函数首先检查参数的合法性,然后将路径拆分成数组。接下来,通过一个循环遍历路径数组,逐级获取对象的值。如果某一级的值不存在,则返回默认值。 这样,我们就实现了一个类似 lodash 的 _.get() 功能的函数。 ### 回答3: lodash 的 _.get() 功能是获取对象指定路径的属性值,如果属性值不存在,可以设置一个默认值。为了实现类似的功能,我们可以采用递归的方式来遍历对象的属性路径,然后返回对应的属性值。 具体实现步骤如下: 1. 首先,我们需要传入两个参数,一个是对象,另一个是属性路径。属性路径可以是一个字符串,也可以是一个数组。 2. 在函数,我们先判断属性路径是否为字符串,如果是,就把它转换成数组的形式,方便后面处理。 3. 我们定义一个辅助函数来实现递归的方式,传入两个参数,一个是对象,一个是属性路径数组。 4. 在辅助函数,我们首先判断属性路径是否为空,如果是,就返回当前对象。 5. 然后,我们取出属性路径数组的第一个元素,并从对象获取对应的属性值。 6. 如果属性值不存在,我们可以设置一个默认值,如果没有传入默认值,就返回 undefined。 7. 如果属性路径数组还有元素,我们递归调用辅助函数,传入对象和剩余的属性路径数组。 8. 最后,我们返回获取的属性值。 这样就实现了类似 lodash 的 _.get() 功能,可以方便地获取对象指定路径的属性值。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值