Blog - wingsico

1
2
3
4
5
6
7
8
9
const pick = (field = "", object = {}) => object[field]
const pluck = (field, array) => array.map(object => pick(field, object))
const deepPluck = (field, array) => array.map(object => deepPick(field, object))
const deepPick = (fields, object = {}) => {
const [first, ...remaining] = fields.split(".")
return (remaining.length) ?
deepPick(remaining.join("."), object[first]) :
object[first]
}

预备知识

接着之前那一段 函数嵌套 的代码,这一段我觉得简单许多,至少不会在一开始就比较懵逼,这里需要了解的知识主要有以下几个:

  1. 默认参数
  2. Array.prototype.map
  3. 箭头函数
  4. 扩展运算符

默认参数

默认参数没什么好说的,详情看ES6 函数的扩展

Array.proptotype.map

Array.prototype.map,参数为函数,函数的参数为数组中的一个值,对数组的每一个值执行一个操作,并把需要的值return出来,每一项return出来的值构成一个新的数组,不改变原数组。

箭头函数

箭头函数这里也没有用到特殊的操作,与上一节一致 (

扩展运算符

主要是数组的解构赋值以及扩展运算符的结合。

举个例子

1
2
3
let [first, ...rest] = [1, 2, 3, 4]
console.log(first) // 1
console.log(rest) // [2, 3, 4]

理解

第一行

第一行代码还是比较好理解的,平常也用的比较多,即提取出对象对应key的value,用es5重写:

1
2
3
4
5
function pick(key, object) {
key = key === undefined ? "" : key
object = object || {}
return object[key]
}

但es6的写法清晰很多,默认参数可以让代码阅读更加明了,可以一目了然的看出哪些参数必须传,哪些参数可以不传,不需要查看函数内部,除此之外,还可以便于后期的迭代,如果之后不需要这个参数了,在对外接口中彻底拿掉这个函数,也不会导致不可用的问题出现。对于是否设置默认参数,要根据当前实际情况来看,如果参数有被遗漏的情况,则最好加上默认参数。

第二行

作用:将一个由对象组成的数组中的每一项(object)中对应的(field)取出,并组成一个新的数组,需要注意的一点,对于数组中某一项没有对应的key的时候,不会跳过而是得到undefined,即长度始终保持与对象数组一致。

举个例子:

1
2
3
let objs = [{'a': 1}, {'c': 1}, {'a': 3}]
let key = 'a'
pluck(key, objs) // [1, undefined, 3]

第三行

与第二行形式结构一致,唯一不同的是map内参数函数的返回值。因此只需了解第四行代码即可。

第四行

首先要注意的就是参数的命名,从pick中的field变为了fields,从函数体可以了解到该函数的功能: 采用递归的形式,取得对象更深层对象的属性值

用一个例子就很好解释:

1
2
3
4
5
6
7
8
9
10
// 一个具有多重对象嵌套的对象
let example = {
"a": {
"b": {
"c": '1'
}
}
}
let keys = "a.b.c" // 即点操作符,取出c的值
deepPluck(keys, example) // 1

小结

分析代码的过程就是一个拆解代码的过程,将一个看似复杂的代码段逐步拆解,分解成一个个的小的易懂的片段,最后将其组合即可。分析后最好再自己实现一遍以加深印象。

 评论