数据结构和运行的结果如下:
const obj = {
a: 0,
c: '',
d: true,
e: {
f: 1,
h: {
e: 0,
f: 2,
},
},
g: {
f: 2,
s: {
e: 1,
}
}
};
console.log(checkIsChildObject({ a: 0 }, obj)); // true
console.log(checkIsChildObject({ e: 0 }, obj)); // true
console.log(checkIsChildObject({ a: 0, c: '' }, obj)); // true
console.log(checkIsChildObject({ a: 0, e: 0 }, obj)); // false
console.log(checkIsChildObject({ e: { f: 1 } }, obj)); // true
console.log(checkIsChildObject({ e: { f: 2 } }, obj)); // false
console.log(checkIsChildObject({ h: { e: 0, f: 2 } }, obj)); // true
console.log(checkIsChildObject({ h: { f: 2, e: 0 } }, obj)); // true
console.log(checkIsChildObject({ h: { f: 2 }, f: 2 }, obj)); // false
console.log(checkIsChildObject({ g: { f: 2 }, c: '' }, obj)); // true
console.log(checkIsChildObject({ g: { f: 2 }, e: 1 }, obj)); // false
实现思路
- 生成一个map对象
- 遍历目标对象,取第一次遍历时的元素匹配到的所有的parentId存储到parentIds中,对对象中后续属性的判断直接使用parentIds去map结构中获取对应的值,判断该值和目标值是否一致即可 注意:使用parentId的原因是:parentId主要用于同级比较时判断两个是否来自同一个parent,避免将第一级数据和第三级数据放在一起时误判为真
/**
* map对象存储结构形如:
* a -> [{ value: 0, parentId: -1}]
* e -> [{ value: { f: 1, ... }, parentId: -1}, { value: 0, parentId: 'h'}]
* h -> [{ value: { e: 0, ... }, parentId: 'e'}}]
* ...
* f -> [{ value: 1, parentId: 'e'}, { value: 2, parentId: 'h'}, { value: 2, parentId: 'g']
*/
function checkIsChildObject(target, obj) {
const map = new Map()
/** 用来生成上述的map结构 */
const handleMap = (obj, parentId = -1, level = 0) => {
Object.entries(obj).forEach(([key, value]) => {
if (map.has(key)) {
let data = map.get(key)
data.push({ value, parentId})
} else {
map.set(key, [{ value, parentId}])
}
if (typeof value === 'object') {
handleMap(value, key, level + 1)
}
})
}
/** 简单的判断o1是否是o2的子对象(只比较一层)*/
const checkObjIsChild = (o1, o2) => {
return Object.entries(o1).every(([key, value]) => JSON.stringify(o2[key]) === JSON.stringify((value)))
}
/** 比较两个值是否一致 */
const checkHasTarget = (value, val) => {
let res = false
if ((typeof value !== 'object' && value === val) || (typeof value === 'object' && checkObjIsChild(value, val))) {
res = true
}
return res
}
handleMap(obj)
let parentIds = [], targetArr = Object.entries(target)
/** 遍历目标对象 */
for (let index in targetArr) {
const [key, value] = targetArr[index]
if (!map.has(key)) {
return false
} else {
/** 存储parentIds */
if (index === '0') {
map.get(key).forEach(({ value: val, parentId }) => {
const res = checkHasTarget(value, val)
if (res) {
parentIds.push(parentId)
}
})
if (!parentIds.length) {
return false
}
} else {
/** 取出parentIds为后续的属性做判断 */
let res = false
for (let parentId of parentIds) {
const objRessArr = map.get(key).filter(item => item.parentId === parentId)
for (let { value: val } of objRessArr) {
const ress = checkHasTarget(value, val)
/** 只要存在一个目标值说明就是符合要求的,直接break */
if (ress) {
res = true
break
}
}
}
/** 没有找到目标值 */
if (!res) {
return false
}
}
}
}
return true
}