我正在尝试创建一个循环遍历配置对象的递归函数,该对象包含必须设置的密钥,稍后将其与appConfig
进行比较,它必须匹配内部的所有密钥(嵌套) unsetConfig
const _ = window._
const UNSET_CONFIG_VAR = 'UNSET'
let config = {
logging: {
hasConsole: UNSET_CONFIG_VAR,
hasSyslog: UNSET_CONFIG_VAR,
processName: UNSET_CONFIG_VAR,
inner: {
test: UNSET_CONFIG_VAR
}
}
}
const unsetConfig = _.clone(config)
function initialize (appConfig) {
const walkConfig = (currentConfigLevel, previousPaths = []) => {
for (const [key, value] of Object.entries(currentConfigLevel)) {
if (_.isObject(value)) {
previousPaths.push(key)
walkConfig(currentConfigLevel[key], previousPaths)
}
const path = previousPaths.length !== 0 ? previousPaths.join('.') : key
if (!_.get(appConfig, path)) {
throw new Error(`Config was missing: ${path}`)
}
}
}
walkConfig(unsetConfig)
}
initialize({
logging: {
hasConsole: true,
hasSyslog: true,
processName: true,
inner: {
as: true
}
}
})
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>
预期输出将会引发错误,因为您可以在initialize
函数中看到test
中缺少logging.inner
密钥。
但不会抛出任何错误。
我现在尝试了不同的设置,但我有点坚持这个。
答案 0 :(得分:2)
如果您只想检查特定路径中是否存在值,则只需使用lodash#has
。使用lodash#get
将从特定路径获取特定属性的值,但使用此值检查此类路径的存在是不可靠的,因为该值可能是一个虚假值。
此外,lodash#has
和lodash#get
接受的路径参数接受字符串或数组,因此您实际上不需要从分隔符连接它们。事实上,当你的一个配置属性包含一个数组时,以这种方式加入它会失败。由于阵列密钥符号被包在一个括号中,例如[0]
或[1]
。
function initialize(appConfig) {
const walkConfig = (config, paths = []) => {
Object.entries(config).forEach(([key, value]) => {
let $paths = paths.concat(key);
if(!_.has(appConfig, $paths)) {
throw new Error(`Config was missing: ${$paths.join('.')}`);
}
if(_.isObject(value)) {
walkConfig(value, $paths);
}
});
};
walkConfig(unsetConfig);
}
const { _ } = window;
const UNSET_CONFIG_VAR = 'UNSET'
let config = {
logging: {
hasConsole: UNSET_CONFIG_VAR,
hasSyslog: UNSET_CONFIG_VAR,
processName: UNSET_CONFIG_VAR,
inner: {
test: UNSET_CONFIG_VAR
}
}
}
const unsetConfig = _.cloneDeep(config); // Clone inner objects as well
function initialize(appConfig) {
const walkConfig = (config, paths = []) => {
Object.entries(config).forEach(([key, value]) => {
let $paths = paths.concat(key);
if(!_.has(appConfig, $paths)) {
throw new Error(`Config was missing: ${$paths.join('.')}`);
}
if(_.isObject(value)) {
walkConfig(value, $paths);
}
});
};
walkConfig(unsetConfig);
}
initialize({
logging: {
hasConsole: false,
hasSyslog: true,
processName: true,
inner: {
as: true
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>