題目(2018-11-19)
有時候我們需要訪問一個對象較深的層次,但是如果這個對象某個屬性不存在的話就會報錯,例如:
var data = { a: { b: { c: 'ScriptOJ' } } }
data.a.b.c // => scriptoj
data.a.b.c.d // => 報錯,代碼停止執(zhí)行
console.log('ScriptOJ') // => 不會被執(zhí)行
請你完成一個safeGet函數(shù),可以安全的獲取無限多層次的數(shù)據(jù),一旦數(shù)據(jù)不存在不會報錯,會返回undefined,例如:
var data = { a: { b: { c: 'ScriptOJ' } } }
safeGet(data, 'a.b.c') // => scriptoj
safeGet(data, 'a.b.c.d') // => 返回 undefined
safeGet(data, 'a.b.c.d.e.f.g') // => 返回 undefined
console.log('ScriptOJ') // => 打印 ScriptOJ
實現(xiàn)
循環(huán)
首先想到的方法就是利用循環(huán)實現(xiàn),每次循環(huán)都進行一次判斷,判斷屬性是否存在,存在繼續(xù),不存在跳出
最早完成的代碼:
const safeGet = (data, path) => {
let result = undefined;
if (!data || !path) {
return result
}
const tempArr = path.split('.');
for (let i = 0; i < tempArr.length; i++) {
const key = tempArr[i];
if (data[key]) {
result = data[key];
data = data[key];
} else {
result = undefined;
break;
}
}
return result;
};
這段代碼至少有兩個可以優(yōu)化的地方:
- 沒有必要聲明
result這個變量,直接使用data即可 -
for循環(huán)內(nèi)部不必break,直接return跳出函數(shù)即可
所以優(yōu)化之后:
const safeGet = (data, path) => {
if (!data || !path) {
return undefined
}
const tempArr = path.split('.');
for (let i = 0; i < tempArr.length; i++) {
const key = tempArr[i];
if (data[key]) {
data = data[key];
} else {
return undefined;
}
}
return data;
};
遞歸
除了使用循環(huán),當(dāng)然也可以遞歸調(diào)用函數(shù)來實現(xiàn):
const safeGet = (data, path) => {
const key = path.split('.')[0];
const restPath = path.slice(2);
if (!data[key]) {
return undefined;
}
if (!restPath) {
return data[key]
}
return safeGet(data[key], restPath)
};
try...catch
看看了討論區(qū),受了一些啟發(fā),還可以使用try...catch實現(xiàn)
const safeGet = (data, path) => {
const tempArr = path.split('.');
try {
while (tempArr.length > 0) {
data = data[tempArr.shift()]
}
return data;
} catch (e) {
return undefined;
}
};
reduce
還可以使用ES6中強大的reduce實現(xiàn),非常簡潔:
const safeGet = (data, path) => {
if (!data || !path) {
return undefined
}
const tempArr = path.split('.');
// 注意初始值是給誰賦值
return tempArr.reduce((total, current) = > {
return (total && total[current]) ? total[current] : undefined
}, data)
};
要注意的一點,
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
參數(shù)initialValue是初始值,是賦值給total的值,不要搞錯。