通过这篇文章,我们已经知道如何将一个数组进行扁平化了,在这篇文章里,我就准备聊聊如何去实现 对象的扁平化,废话不多说,开搞!

ppx2.jpg

正文

先给出题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
需要被铺平的对象
{
a: 1,
b: '2',
c: ()=>{},
d: undefined,
e: {
f: {
g: 1
}
},
h: {},
i: [],
j: [1,{k:2}],
l: [[]],
m: {
n: {}
}
}

铺平后
{
a: 1,
b: '2',
c: ()=>{},
d: undefined,
'e.f.g':1,
h: {},
i: {},
'j[0]': 1,
'j[1].k': 2,
'l[0]': [],
'm.n': {}
}

看到这个题目,我们进行分析后,可以得知以下几点的信息

  1. 对于 非对象且非数组类型 的属性值,是最终用来进行赋值给铺平后的对象的
  2. 对于 空数组或空对象,直接使用其值,不再进行铺平
  3. 对于 非空数组,进行铺平处理
  4. 对于 非空对象,进行铺平处理

铺平处理其实就是一个 递归过程,终止条件就是下面两种

  1. 值为非数组且非对象
  2. 值为空数组或空对象

结合上述分析,下面给出代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function flat(obj) {
const res = {}

function recursion(k,v) {
if(!/Object|Array/.test(Object.prototype.toString.call(v))) {
res[k] = v
}else if(Array.isArray(v)) {
if(!v.length) {
res[k] = []
return
}
v.forEach((item,index)=>{
recursion(`${k}[${index}]`,item)
})
}else {
const keys = Object.keys(v)
if(!keys.length) {
res[k] = {}
return
}
keys.forEach(item=>{
recursion(k ? `${k}.${item}` : item, v[item])
})
}
}

recursion('',obj)
return res
}

简单对上述代码进行分析

  1. 定义一个 res对象,用于保存被铺平后的属性

  2. 定义一个递归函数 recursion,用于铺平,接受 kv 两个参数,然后对 v 进行类型判断

    • 如果v是 非数组且非对象,那么就将v跟对应的k组合起来
    • 如果是 数组,首先判断 是否为空,如果是,就直接将k与v组合起来,如果不是,就遍历数组的每一项,并将k设置为 ${k}[${index}],用于下一轮的递归
    • 如果是对象,首先用 Object.keys 获取所有的键,然后判断是否为空对象,如果是,就直接将k与v组合起来,如果不是,就遍历keys数组,然后将k设为 (k ? `${k}.${item}` : item,用于下一轮的递归,需要说明的是,k为空,表示当前是 根属性,不需要前缀
  3. 调用递归函数,需要注意的是,需要将k参数设为 空字符串,表明是 根属性

  4. 返回res对象

666.jpg