我想向嵌套的 JavaScript 物件添加一些資料,但是我不知道物件樹已經存在多少。如果結構不存在,我想添加它,但如果它在那里標記有其他一些默認資料,我也要保留相同的資訊。
理想情況下,我不想為此使用第三方庫。
在我的示例中,我有以下物件結構,這些物件結構將有無窮無盡的組合,因此如果它不存在,它需要為我生成結構。
{
level1: {
level2: {
level3: {
property1: 'test'
}
}
}
}
我希望能夠給它一些值,創建結構 - 如果結構存在,添加一些默認值,如果沒有,則使用默認值創建結構。
我有以下內容,可以完成這項作業,但對我來說看起來很亂,我想知道是否有更好的方法來實作這一目標?
const updateNestedObject = (obj, level1, level2, level3, defaultProps) => {
if (obj && obj[level1] && obj[level1][level2] && obj[level1][level2][level3]) {
obj[level1][level2][level3] = { ...defaultProps, ...obj[level1][level2][level3] }
} else if (obj && obj[level1] && obj[level1][level2] && !obj[level1][level2][level3]) {
obj[level1][level2][level3] = defaultProps
} else if (obj && obj[level1] && !obj[level1][level2]) {
obj[level1][level2] = { [level3]: defaultProps }
} else if (obj && !obj[level1]) {
obj[level1] = { [level2]: { [level3]: defaultProps } }
} else {
obj = { [level1]: { [level2]: { [level3]: defaultProps } } }
}
return obj
}
uj5u.com熱心網友回復:
這可以通過遞回來完成。以下是如何實作它的概述(未針對所有情況進行測驗):
function mergeRecursive(targetObject, sourceObject) {
Object.keys(sourceObject).forEach(function(key) {
if (typeof sourceObject[key] === "object") {
if (targetObject[key] === undefined) {
targetObject[key] = {};
}
mergeRecursive(targetObject[key], sourceObject[key]);
} else {
targetObject[key] = sourceObject[key];
}
});
}
let foo = {
"level1": {
"bar": "baz"
}
};
let bar = {
level1: {
level2: {
level3: {
property1: "test"
}
}
}
};
mergeRecursive(foo, bar);
console.log(foo);
uj5u.com熱心網友回復:
你可以做這樣的事情,你回圈遍歷鍵并逐級遍歷物件。每個回圈我們設定一個外部變數 - level- 到當前的,所以我們不必使用以前的鍵來達到當前級別。即,我們避免必須做obj[ level1 ][ level2 ][ level3 ] = ...,相反,我們可以做level = ...
這樣,我會說最好傳遞一個引數keys,它是一個陣列。有了這個,您不僅限于 3 個嵌套鍵,而是可以傳遞任何您想要的數字。
const updateNestedObject = ( obj, keys, defaultProps ) => {
let level = obj;
for ( let i = 0; i <= keys.length-1; i ) {
let key = keys[ i ];
if ( i === keys.length-1 ) {
level[ key ] = { ...defaultProps };
return;
}
if ( !level[ key ] ) {
level[ key ] = {};
}
level = level[ key ];
}
};
const object = {};
updateNestedObject( object, [ "foo", "bar", "baz" ], { property: "test" } )
console.log( object );
const object2 = { foo: { bar: {} } };
updateNestedObject( object2, [ "foo", "bar", "baz" ], { property: "test" } )
console.log( object2 );
const object3 = { foo: { bar: {} } };
updateNestedObject( object3, [ "foo", "bar" ], { property: "test" } )
console.log( object3 );
請注意,這確實會就地更改物件。
uj5u.com熱心網友回復:
setPath我經常使用的函式的一個小變種會以一種相當簡單的方式做到這一點:
const mixDeep = ([p, ...ps]) => (v) => (o) =>
p == undefined ? v : Object .assign (
Array .isArray (o) || Number .isInteger (p) ? [] : {},
{...o, [p]: ps .length ? mixDeep (ps) (v) ((o || {}) [p]) : {...v, ...(o || {}) [p]}},
)
const myFunc =
mixDeep (['level1', 'level2', 'level3']) ({some: 'default', props: 'here'})
console .log (myFunc ({foo: 'bar'}))
console .log (myFunc ({foo: 'bar', level1: {baz: 'qux'}}))
console .log (myFunc ({foo: 'bar', level1: {baz: 'qux', level2: {corge: 'grault'}}}))
console .log (myFunc ({foo: 'bar', level1: {baz: 'qux', level2: {corge: 'grault', level3: {garply: 'waldo'}}}}))
.as-console-wrapper {max-height: 100% !important; top: 0}
setPath 設定路徑的值,根據需要構建中間節點。 mixDeep 將值混合到路徑末尾的值中,再次構建缺少的任何中間節點。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/447649.html
標籤:javascript 目的 递归 ecmascript-6
上一篇:C 中物件和變數的區別
