JS:如何根据数组中的逻辑条件搜索对象中是否存在字段



我有以下JS对象:

let obj = {
b: 1,
c: 1,
d: 2
}

我想写一个函数,它接受一个输入数组,并检查这个数组中列出的字段是否存在于obj中,但我希望条件中有逻辑。所以类似的东西

arr = ['b', 'c' || 'd']   (returns true if obj has an entry for `b`, and for either `c` or `d`)

arr = ['c' && 'd']   (returns true only if obj has entries for both `c` and `d`)

所以在我的函数中,我想象写一个类似的条件

return arr.forEach(condition => object[condition])

我该如何处理?

您将不得不为自己编写某种能够处理逻辑检查的规则引擎。以下是使用对象的基本思想。

function basicIdea(rules, obj) {
const checksFns = {
and: arr => arr.every(checkIt),
or: arr => arr.some(checkIt),
};
const hasKey = key => key in obj;
const checkIt = item => {
if (typeof item === 'object') {
const {
op,
checks
} = item;
return checksFns[op](checks);
}
return hasKey(item);
}
return checkIt(rules);
}
var obj1 = {
a: 1,
b: 1,
c: 1
};
console.log('check and good', basicIdea({
op: 'and',
checks: ['a', 'b', 'c']
}, obj1));
console.log('check and bad', basicIdea({
op: 'and',
checks: ['a', 'b', 'd']
}, obj1));
console.log('check or good', basicIdea({
op: 'or',
checks: ['d', 'a']
}, obj1));
console.log('check or bad', basicIdea({
op: 'or',
checks: ['d', 'e']
}, obj1));
console.log('check and or good', basicIdea({
op: 'and',
checks: ['a', {
op: 'or',
checks: [
'b',
'c'
]
}],
},
obj1));

console.log('check and or bad', basicIdea({
op: 'and',
checks: ['a', {
op: 'or',
checks: [
'd',
'e'
]
}],
},
obj1));

您可以执行以下操作:编写一个类似checkFields函数的fintion来接收对象,以及一个表示要检查的条件的字符串,例如:"a||b";或";a&b";或";a";,它会用||和&并检查条件,并根据条件是否正确返回真/假。接下来,calcResult函数将获取一个类似["a||b","a"]的数组,并将其中的每个项传递给checkFields函数,如果所有结果都为true,则返回true。

const checkFields = (obj, condition) => {
let result = false;
if (condition.includes("||")) {
const [field1, field2] = condition.split("||");
if (obj.hasOwnProperty(field1) || obj.hasOwnProperty(field2)) {
result = true;
} else result = false;
} else if (condition.includes("&&")) {
const [field1, field2] = condition.split("&&");
if (obj.hasOwnProperty(field1) && obj.hasOwnProperty(field2)) {
result = true;
} else result = false;
} else {
if (obj.hasOwnProperty(condition)) {
result = true;
} else result = false;
}
return result;
};

const obj = {
b: 1,
c: 1,
d: 2
};
const arr1 = ['b', 'c', 'd||b', 'a||f'];
const arr2 = ['b', 'c&&b', 'd&&b', 'a||d'];
const calcResult = (array) => array.reduce((acc, item) => acc && checkFields(obj, item), true);

console.log(calcResult(arr1));
console.log(calcResult(arr2));

以编程方式构建规则并对其进行评估。

/* library code */
const hasProp = prop => obj =>
prop in obj;

const or = (...conditions) => obj =>
conditions.some(condition => condition(obj));
const and = (...conditions) => obj =>
conditions.every(condition => condition(obj));

const apply = rules => obj =>
rules.map(fn => fn(obj));
/* /library code */
const arr = [
hasProp("a"), // false
hasProp("b"), // true
or(hasProp("a"), hasProp("b")), // true
or(hasProp("a"), hasProp("z")), // false
and(hasProp("c"), hasProp("d")), // true
and(hasProp("a"), hasProp("d")), // false
and(hasProp("b"), hasProp("c"), hasProp("d")), // true
and(or(hasProp("a"), hasProp("b")), and(hasProp("d"), hasProp("d"))) // true
];
const checkAllRules = apply(arr);
console.log(checkAllRules(obj));
<script>
//set up data
let obj = {
b: 1,
c: 1,
d: 2
}
</script>

这可以通过更多的检查(比如属性是否有特定值,如果它是Date对象)和运算符(比如not来反转结果)来扩展:

/* library code */
const hasProp = prop => obj =>
prop in obj;

const hasValue = (prop, value) => obj =>
obj[prop] === value;
const isDateObject = obj =>
obj instanceof Date;

const or = (...conditions) => obj =>
conditions.some(condition => condition(obj));
const and = (...conditions) => obj =>
conditions.every(condition => condition(obj));
const not = rule => obj => 
!rule(obj);

const apply = rules => obj =>
rules.map(fn => fn(obj));
/* /library code */
const arr = [
hasValue("b", 1), // true
hasValue("b", 7), // false
isDateObject, //false
not(hasProp("a")), //true
or(hasValue("b", 7), hasValue("d", 2)), // true
and(hasValue("c", 1), not(isDateObject)), // true
];
const checkAllRules = apply(arr);
console.log(checkAllRules(obj));
<script>
//set up data
let obj = {
b: 1,
c: 1,
d: 2
}
</script>