有什么更好的方法來做到這一點。根據它們的存在,我將兩個屬性值(來自兩個不同的物件)中的任何一個分配給第三個資料結構。
如果args物件的值為空值,則從物件訪問非空值default并將其分配給最終結構。
return {
first: {
visible: args.first?.visible ?? defaulttest.first?.visible,
emoji: args.first?.emoji ?? defaulttest.first?.emoji,
style: args.first?.style ?? defaulttest.first?.style,
},
back: {
visible: args.back?.visible ?? defaulttest.back?.visible,
emoji: args.back?.emoji ?? defaulttest.back?.emoji,
style: args.back?.style ?? defaulttest.back?.style,
},
page: {
visible: args.page?.visible ?? defaulttest.page?.visible,
emoji: args.page?.emoji ?? defaulttest.page?.emoji,
style: args.page?.style ?? defaulttest.page?.style,
},
forward: {
visible: args.forward?.visible ?? defaulttest.forward?.visible,
emoji: args.forward?.emoji ?? defaulttest.forward?.emoji,
style: args.forward?.style ?? defaulttest.forward?.style,
},
last: {
visible: args.last?.visible ?? defaulttest.last?.visible,
emoji: args.last?.emoji ?? defaulttest.last?.emoji,
style: args.last?.style ?? defaulttest.last?.style,
},
Mdelete: {
visible: args.Mdelete?.visible ?? defaulttest.Mdelete?.visible,
emoji: args.Mdelete?.emoji ?? defaulttest.Mdelete?.emoji,
style: args.Mdelete?.style ?? defaulttest.Mdelete?.style,
},
removeBtn: {
visible: args.removeBtn?.visible ?? defaulttest.removeBtn?.visible,
emoji: args.removeBtn?.emoji ?? defaulttest.removeBtn?.emoji,
style: args.removeBtn?.style ?? defaulttest.removeBtn?.style,
},
};
uj5u.com熱心網友回復:
從我上面的評論...
1/2 ... OP 實際上并沒有真正進行比較。對于特定的一組屬性,OP 在目標物件上查找每個屬性,并且只有在它具有空值的情況下,才會從源物件的對應項對缺失的屬性進行分配。因此,我會選擇的一種方法是......
2/2 ... 實作一個通用函式,它合并兩個物件,只有在目標結構還沒有提供非空值的情況下才能寫入/分配源屬性。這個函式必須被呼叫兩次,一次是為了
args和defaulttest第二次回傳完全空的資料結構和args。
上述宣告有點雄心勃勃,因為至少有兩種策略可以實作這種合并。
因此,下面提供的示例代碼實作了兩種方法
一種稱為refit,它遵循推送/修補議程,因為強制將源物件中的每個非空屬性分配給目標物件的非空對應物。
第二個,稱為revive,它類似于一種拉動方法,因為它只是將無效的目標物件屬性與其非無效的源物件對應物重新分配。
他們為一個相同的預設產生的結果的差異將被證明...
// "refit" ... a pushing/patching approach.
// - force the assignement of every non nullish property in source
// to its non nullish counterpart in target ... hence a *refit*.
function refitNullishValuesRecursively(target, source) {
if (
// are both values array-types?
Array.isArray(source) &&
Array.isArray(target)
) {
source
// for patching always iterate the source items ...
.forEach((sourceItem, idx) => {
// ... and look whether a target counterpart exists.
if (target[idx] == null) {
// either assign an existing structured clone ...
if (sourceItem != null) {
target[idx] = cloneDataStructure(sourceItem);
}
} else {
// ... or proceed recursively.
refitNullishValuesRecursively(target[idx], sourceItem);
}
});
} else if (
// are both values object-types?
source && target &&
'object' === typeof source &&
'object' === typeof target
) {
Object
// for patching ...
.entries(source)
// ... always iterate the source entries (key value pairs) ...
.forEach(([key, sourceValue], idx) => {
// ... and look whether a target counterpart exists.
if (target[key] == null) {
// either assign an existing structured clone ...
if (sourceValue != null) {
target[key] = cloneDataStructure(sourceValue);
}
} else {
// ... or proceed recursively.
refitNullishValuesRecursively(target[key], sourceValue);
}
});
}
return target;
}
// "revive" ... a pulling approach.
// - just reassign the nullish target properties with their
// non nullish source counterparts ... hence a *revive*.
function reviveNullishValuesRecursively(target, source) {
if (
// are both values array-types?
Array.isArray(target) &&
Array.isArray(source)
) {
target
// for fixing always iterate the target items.
.forEach((targetItem, idx) => {
if (targetItem == null) {
// either assign an existing structured clone ...
target[idx] = cloneDataStructure(source[idx]) ?? targetItem;
} else {
// ... or proceed recursively.
reviveNullishValuesRecursively(targetItem, source[idx]);
}
});
} else if (
// are both values object-types?
target && source &&
'object' === typeof target &&
'object' === typeof source
) {
Object
// for fixing ...
.entries(target)
// ... always iterate the target entries (key value pairs).
.forEach(([key, targetValue], idx) => {
if (targetValue == null) {
// either assign an existing structured clone ...
target[key] = cloneDataStructure(source[key]) ?? targetValue;
} else {
// ... or proceed recursively.
reviveNullishValuesRecursively(targetValue, source[key]);
}
});
}
return target;
}
const cloneDataStructure =
('function' === typeof structuredClone)
&& structuredClone
|| (value => JSON.parse(JSON.stringify(value)));
const targetBlueprint = {
x: { xFoo: 'foo', xBar: 'bar', xBaz: { xBiz: null } },
y: { yFoo: 'foo', yBar: null },
};
const patch = {
x: { xFoo: null, xBar: null, xBaz: { xBiz: 'biz' } },
y: { yFoo: null, yBar: 'bar', yBaz: { yBiz: 'biz' } },
};
let target = cloneDataStructure(targetBlueprint);
console.log('"refit" ... a pushing/patching approach.');
console.log('before refit ...', { target, patch });
refitNullishValuesRecursively(target, patch);
console.log('after refit ...', { target, patch });
target = cloneDataStructure(targetBlueprint);
console.log('"revive" ... a pulling approach.');
console.log('before revive ...', { target, patch });
reviveNullishValuesRecursively(target, patch);
console.log('after revive ...', { target, patch });
.as-console-wrapper { min-height: 100%!important; top: 0; }
至于以創建一種配置物件為目標的 OP 示例,可以完全修補/重新調整臨時或當前配置的克隆args,而在最后一步中,可以通過提供來控制配置物件的最終結構最基本的空配置庫,剛剛被之前創建的完整補丁/改裝配置恢復。
function refitNullishValuesRecursively(target, source) {
if (Array.isArray(source) && Array.isArray(target)) {
source
.forEach((sourceItem, idx) => {
if (target[idx] == null) {
if (sourceItem != null) {
target[idx] = cloneDataStructure(sourceItem);
}
} else {
refitNullishValuesRecursively(target[idx], sourceItem);
}
});
} else if (
source && target &&
'object' === typeof source &&
'object' === typeof target
) {
Object
.entries(source)
.forEach(([key, sourceValue], idx) => {
if (target[key] == null) {
if (sourceValue != null) {
target[key] = cloneDataStructure(sourceValue);
}
} else {
refitNullishValuesRecursively(target[key], sourceValue);
}
});
}
return target;
}
function reviveNullishValuesRecursively(target, source) {
if (Array.isArray(target) && Array.isArray(source)) {
target
.forEach((targetItem, idx) => {
if (targetItem == null) {
target[idx] = cloneDataStructure(source[idx]) ?? targetItem;
} else {
reviveNullishValuesRecursively(targetItem, source[idx]);
}
});
} else if (
target && source &&
'object' === typeof target &&
'object' === typeof source
) {
Object
.entries(target)
.forEach(([key, targetValue], idx) => {
if (targetValue == null) {
target[key] = cloneDataStructure(source[key]) ?? targetValue;
} else {
reviveNullishValuesRecursively(targetValue, source[key]);
}
});
}
return target;
}
const cloneDataStructure =
('function' === typeof structuredClone)
&& structuredClone
|| (value => JSON.parse(JSON.stringify(value)));
const defaultConfig = {
first: {
visible: 'default.first.visible',
emoji: 'default.first.emoji',
style: 'default.first.style',
},
forward: {
visible: 'default.forward.visible',
emoji: 'default.forward.emoji',
style: 'default.forward.style',
},
removeBtn: {
visible: 'default.removeBtn.visible',
emoji: 'default.removeBtn.emoji',
style: 'default.removeBtn.style',
},
};
const currentConfig = {
first: {
visible: 'current.first.visible',
emoji: 'current.first.emoji',
style: 'current.first.style',
},
forward: {
visible: 'current.forward.visible',
emoji: null,
},
FOO: {
visible: 'current.FOO.visible',
emoji: 'current.FOO.emoji',
style: 'current.FOO.style',
}
};
function getConfiguration(baseConfig) {
return reviveNullishValuesRecursively(
cloneDataStructure(baseConfig),
refitNullishValuesRecursively(
cloneDataStructure(currentConfig),
defaultConfig,
),
);
}
console.log(
getConfiguration({
first: null,
forward: null,
removeBtn: null,
})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
uj5u.com熱心網友回復:
我同意背景關系會有所幫助。
但是從這一點來看,要比較兩個物件,您可以用一些唯一值標記它們。這是您擁有并創建它們的最簡單方法。
如果您無法通過唯一識別符號標記它們,您可以使用哈希 json https://www.npmjs.com/package/json-hash之類的東西 我使用了一段時間但因為我正在尋找一些東西而離開了它更好的。
在下一步中,我創建了自己的解決方案來生成唯一值(在應用程式背景關系中)和比較器服務來比較這些我無法簽名的。
const createUniqueStringCache = { stamp: new Date(), add: 0 };
function createUniqueString() {
const currentStamp = new Date();
if (createUniqueStringCache.stamp === currentStamp) {
createUniqueStringCache.add = 1;
} else {
createUniqueStringCache.stamp = currentStamp;
createUniqueStringCache.add = 0;
}
const uniqueStringNumbers = String(createUniqueStringCache.stamp) createUniqueStringCache.add;
const uniqueStringCharacters = uniqueStringNumbers
.split("")
.map(it => String.fromCharCode(97 Number(it)))
.join("");
return uniqueStringCharacters;
}
和比較器服務。
uj5u.com熱心網友回復:
如果您的物件結構是您呈現的結構,您可以執行以下操作:
function normalize(input, default) {
// Loop on the outer keys
Object.keys(input).forEach(mainKey => {
// Loop on the inner keys
Object.keys(input[mainKey]).forEach(key => {
// set the value of the key as itself or default if null
input[mainKey][key] = input[mainKey]?.[key] ?? default[mainKey]?.[key]
})
})
return input;
}
呼叫normalize(args, defaulttest)您將在每個內部鍵上回圈,檢查它是否存在,如果不存在,則將其替換為同一路徑中的默認值。
例子:
const x = {
a: {a1: '1', a2: '2'},
b: {b1: '1', b2: null}
}
const y = {b: {b2: '5'}}
console.log(normalize(x,y))
輸出:
{
"a": {
"a1": "1",
"a2": "2"
},
"b": {
"b1": "1",
"b2": "5"
}
}
使用這種方法,您必須在 args 輸入中有密鑰。如果缺少密鑰,則不會用默認值替換。為了使它即使使用不存在的鍵也可以作業,例如,您需要使用具有所有可能路徑的第三種結構。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/478579.html
標籤:javascript 目的 数据结构 合并 比较
上一篇:在陣列中的物件值后添加逗號
下一篇:如何為物件添加值并洗掉當前值?
