对象层级嵌套太深获取时报错
例如
const o = {}
o.b.a.c
// Uncaught TypeError: Cannot read property 'a' of undefined
const d = {b: null }
d.b.a.c
// Uncaught TypeError: Cannot read property 'a' of null
实际业务中在vue的template中,获取后端返回的数据报错
<div class="report-main-text">
{{ reportData.examineResult.examineImpression }}
</div>
解决方案
举例
const object = { a: [{ b: { c: 3 } }] };
const defaultValue = 'defaultValue'
const a = safeGet(object, ["a", "0", "b", "c"], defaultValue )
// val => 3
const b = safeGet(object, ["a", "0", "b", "c", "b"]);
// b=> defaultValue 并且 报错
通过遍历property数组,取相应的值,如果为空就返回错误信息并且采用默认值,如果遍历完整就取相应的值
// a: any
function isArray(a) {
return Array.isArray(a);
}
function isEmpty(a) {
return a == null || typeof a !== "object";
}
function throwErrorInfo(obj, state, properties, n) {
const errorProperty = properties[n];
const propertiesInfo = properties.join();
console.error(
`Cannot read property ${errorProperty} of ${state}`,
obj,
properties
);
}
function safeGet(obj, properties, defaultValue) {
let state = obj;
function computeArrayProperties() {
for (let i = 0; i < properties.length; i++) {
const property = properties[i];
if (isEmpty(state)) {
throwErrorInfo(obj, state, properties, i);
return defaultValue;
} else {
state = state[property];
}
}
}
if (isArray(properties)) {
computeArrayProperties()
}
return state;
}
利用递归实现,实际就是替换 state , n,逻辑调理清晰
function safeGetByIter(obj, properties, defaultValue = "") {
const len = properties.length;
const equal = (x, y) => x === y
function iterFn(state, n) {
if (equal(n, len)) {
return state;
} else if (isEmpty(state)) {
throwErrorInfo(obj, state, properties, n);
return defaultValue;
} else {
return iterFn(state[properties[n]], n + 1);
}
}
if (isArray(properties)) {
return iterFn(obj, 0);
}
return defaultValue
}
延展
实际在lodash库中,就有相关的解决方案 _.get,文档链接