对象链式取值(如loadsh的_.get()方法)在项目中的应用

  目录

对象的链式取值在项目中的应用场景。

对象链式取值(如loadsh的_.get()方法)在项目中的应用

相信大家在从后端获取数据的时候,像这样res.data.rows.count来获取数据的情况很多,如果后台返回的格式不对了,或则data是个null,那么很容易报Uncaught TypeError: Cannot read property ‘goods’ of undefined这样的错。
我们一般会这样写:

1
2
3
if(res && res.data && res.data.rows && res.data.count) {
...
}

不过这么写实在是有些麻烦,我一般的做法是直接catch住error,然后定位到具体错误在哪,在改正。
不过,最近在网上看到一篇专门写关于对象的链式取值的文章,里边写了大概4种解决方法,这里我只记录学习了其中一种,也是兼容性最好的一种,就想使用loadsh的_.get方法,先看看loadsh是怎么用的,见下边

1
2
3
4
5
6
7
var object = { 'a': [{ 'b': { 'c': 3 } }] };
_.get(object, 'a[0].b.c');
// => 3
_.get(object, ['a', '0', 'b', 'c']);
// => 3
_.get(object, 'a.b.c', 'default');
// => 'default'

使用方法一目了然,第一个参数:对象,第二个参数:链式字符串,第三个参数是,如果按照这个链式字符串在对象中取不到值,返回这个默认值。这样写的话,就像上边即使后台同事更改了数据结构,不会报错,而是返回默认值。(不过这种写法我觉得也有不好的地方,那就是不容易发现错误,后台返回的数据结构都变了,而我们前台并没有出现异常,而是返回来初始写的默认值,是不是有点。。。)不过,这种写法在其它场合我想一定会有用武之地。
我现在的项目中并没有用到loadsh这个库,但是还想用咋办呢?自己写一个喽,还好,写法简单,容易理解,注意,下边给出的代码交通过函数解析字符串方式来处理的。

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 get (obj, props, def) {
if((obj == null) || obj == null || typeof props !== 'string') return def;
const temp = props.split('.');
const fieldArr = [].concat(temp);
temp.forEach((e, i) => {
if(/^(\w+)\[(\w+)\]$/.test(e)) {
const matchs = e.match(/^(\w+)\[(\w+)\]$/);
const field1 = matchs[1];
const field2 = matchs[2];
const index = fieldArr.indexOf(e);
fieldArr.splice(index, 1, field1, field2);
}
})
return fieldArr.reduce((pre, cur) => {
const target = pre[cur] || def;

if(target instanceof Array) {
return [].concat(target);
}
if(target instanceof Object) {
return Object.assign({}, target)
}
return target;
}, obj)
}
var c = {a: {b : [1,2,3] }}
get(c ,'a.b') // [1,2,3]
get(c, 'a.b[1]') // 2
get(c, 'a.d', 12) // 12

其实,在项目无论如何使用都没什么问题,即使什么都不做,最后项目完成时,也一定会因为出现报错而改正过来,最多就是不够健壮。我觉得这个函数解析字符串的方式很好,值得举一反三,值得学习。