演算法練習04 取物件的深層屬性
阿新 • • 發佈:2018-12-03
題目(2018-11-19)
有時候我們需要訪問一個物件較深的層次,但是如果這個物件某個屬性不存在的話就會報錯,例如:
var data = { a: { b: { c: 'ScriptOJ' } } }
data.a.b.c // => scriptoj
data.a.b.c.d // => 報錯,程式碼停止執行
console.log('ScriptOJ') // => 不會被執行
請你完成一個safeGet
函式,可以安全的獲取無限多層次的資料,一旦資料不存在不會報錯,會返回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
實現
迴圈
首先想到的方法就是利用迴圈實現,每次迴圈都進行一次判斷,判斷屬性是否存在,存在繼續,不存在跳出
最早完成的程式碼:
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; };
這段程式碼至少有兩個可以優化的地方:
- 沒有必要宣告
result
這個變數,直接使用data
即可 for
迴圈內部不必break
,直接return
跳出函式即可
所以優化之後:
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; };
遞迴
除了使用迴圈,當然也可以遞迴呼叫函式來實現:
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
看看了討論區,受了一些啟發,還可以使用try...catch
實現
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
實現,非常簡潔:
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)
引數initialValue
是初始值,是賦值給total
的值,不要搞錯。