我有一个像这样的对象:
const obj = {
name: "one",
created: "2022-05-05T00:00:00.0Z",
something: {
here: "yes"
}
}
我可以逐个检查它是否具有某些属性:
assert( obj.name !== undefined && obj.name === "one")
assert( obj.something !== undefined && obj.something.here !== undefined && obj.something.here === "yes")
是否有一种方法来实现相同的传递另一个对象进行比较?另一个对象将具有更少的值(在本例中,我不关心created
属性是否存在)
类似:
const obj = {
name: "one",
created: "2022-05-05T00:00:00.0Z",
something: {
here: "yes"
}
}
hasAllOf(obj, {
name: "one",
something: {
here: "yes"
}
}) // returns true
使用lodash或其他库吗?
您可以使用类型检查助手is
-
hasAllOf
const is = (t, T) =>
t?.constructor === T
const hasAllOf = (a, b) =>
is(a, Object) && is(b, Object) || is(a, Array) && is(b, Array)
? Object.keys(b).every(k => hasAllOf(a[k], b[k]))
: a === b
const obj = {
name: "one",
created: "2022-05-05T00:00:00.0Z",
something: {
here: "yes",
and: ["this", 2, { f: "three" }]
}
}
console.log(
hasAllOf(obj, {
name: "one",
something: {
here: "yes",
and: ["this", 2, { f: "three" }]
}
})
)
通过使用另一个条件
支持Map
和Set
const is = (t, T) =>
t?.constructor === T
const hasAllOf = (a, b) => {
switch (true) {
case is(a, Object) && is(b, Object) || is(a, Array) && is(b, Array):
return Object.keys(b).every(k => hasAllOf(a[k], b[k]))
case is(a, Set) && is(b, Set):
return [...b].every(v => a.has(v))
case is(a, Map) && is(b, Map):
return [...b.keys()].every(k => hasAllOf(a.get(k), b.get(k)))
default:
return a === b
}
}
const obj = {
name: new Map([[1, "one"], [2, "two"]]),
created: "2022-05-05T00:00:00.0Z",
something: {
here: new Set("yes", "ok"),
and: ["this", 2, { f: "three" }],
}
}
console.log(
hasAllOf(obj, {
name: new Map([[1, "one"]]),
something: {
here: new Set("yes"),
and: ["this", 2, { f: "three" }]
}
})
)
lodash isEqual函数可能就是您正在寻找的。https://lodash.com/docs/isEqual
const obj = {
name: "one",
created: "2022-05-05T00:00:00.0Z",
something: {
here: "yes"
}
}
_.isEqual(delete obj.created, delete {
name: "one",
created: "2022-05-05T00:00:00.0Z",
something: {
here: "yes"
}}.created); //returns true
或
const obj = {
name: "one",
created: "2022-05-05T00:00:00.0Z",
something: {
here: "yes"
}
}
delete obj.created;
_.isEqual(obj, {
name: "one",
something: {
here: "yes"
}}.created); //returns true
你甚至可以使用不同的lodash函数(_.cloneDeep
)来复制原始的,这样你就不会改变它了。
function hasAllOf(obj,data) {
let obj_keys = Object.keys(obj)
for (let key in data) {
if (!(obj_keys.includes(key))) {
return false;
}
if (typeof data[key] === "object" && typeof obj[key] === "object")
{
let res = hasAllOf(obj[key], data[key])
if (!res) {
return res;
}
res = hasAllOf(data[key], obj[key])
if (!res) {
return res;
}
}
else if (data[key] !== obj[key])
{
return false;
}
}
return true;
}
const obj =
{
name: "one",
created: "2022-05-05T00:00:00.0Z",
something:
{
here: "yes",
}
}
const data =
{
name: "one",
something:
{
here: "yes",
},
}
console.log(hasAllOf(obj, data))
我认为_。consto与我所寻找的非常匹配,它有点冗长,但比逐一进行所有比较(特别是在较大的对象中)要好得多,也更清晰
_.conformsTo(obj, {
name: (n) => n === "one",
created: (c) => _.isString(c),
// calling _conformsTo on nested objects
something: (s) => _.conformsTo(s, {
here: (h) => h === "yes"
})
})
更新…
我甚至可以创建一个is
和conformsTo
函数,返回一个"部分应用"。函数,使其更清晰。
完整的示例:
const _ = require('lodash')
const is = (expected) => (actual) => actual === expected
const conformsTo = (template) => (actual) => _.conformsTo(actual, template)
_.conformsTo(
{ // source
name: "one",
created: "2022-05-05T00:00:00.0Z",
something: {
here: "yes"
}
},
{ // "spec"
name: is('one'),
something: conformsTo({
here: is("yes")
})
}
)