Javascript 对象比较:检查一个对象是否包含整个其他对象

Javascript 对象比较:检查一个对象是否包含整个其他对象,javascript,Javascript,我有两个目标。它们的结构看起来有点像这样: { education: ["school", "institute"], courses: ["HTML", "JS", "CSS"], Computer: { "OS":"WXP", "WS":"NotePad" } } 第二点: { education: ["school", "university", "institute", "collage"], courses: ["HTML

我有两个目标。它们的结构看起来有点像这样:

{
 education: ["school", "institute"],
 courses: ["HTML", "JS", "CSS"],
 Computer: {
        "OS":"WXP",
        "WS":"NotePad"
         }
 }
第二点:

{
 education: ["school", "university", "institute", "collage"],
 courses: ["HTML", "CSS", "JS", "Managing", "Directing"],
 Computer: {
        "OS":"WXP",
        "WS":"NotePad",
        "AV":"Avast"
         },
 something: function(){...},
 other: "thing"

}
您可能注意到,第二个对象包含整个第一个对象,以及第一个对象没有的一些项目。
我需要比较这两个对象,如果第二个对象包含第一个对象的每一项,我需要得到一个答案(
true
-
false
true
-如果第一个对象的所有项目也在第二个对象中
false
-如果第一个对象的至少一个项目不在第二个对象中,例如:如果第二个对象没有“css”课程

(第一个是要求,第二个是该人员所拥有的。我需要检查该人员是否具备所有要求)

可以是普通的JS、jQuery等等。我不喜欢使用服务器端语言

有办法吗


谢谢

Edit:没有注意到
merge
更改了第一个参数。。。更改了代码,但仍会导致obj2更改。您可以添加
。.cloneDeep(obj2)
,这应该可以解决这个问题,但到那时,我的解决方案似乎并不那么优雅。还使用
cloneDeep
更新了演示

Edit2:由于
JSON.stringify
要求比较对象中的对象属性顺序相同,因此可以使用类似的命令。但是,在演示中,您可以看到它是有效的,因此我想说,对于您的情况,使用
\uuu.merge
JSON.stringify
是可靠的

使用,您可以使用
\合并
,并检查结果是否与较大的对象相同

function(obj1, obj2) {
    var obj3 =_.merge(_.cloneDeep(obj2), obj1);
    return JSON.stringify(obj3) === JSON.stringify(obj1);
}

当然,另一种选择是使用vanilla JS迭代整个对象。

JavaScript(在ES5中)有两种复合本机类型(我假设您的代码中没有任何自定义集合,如果有-我假设它们支持“旧”迭代协议(具有.length)

这是一个带注释的解决方案草图。我运行它不是为了让您了解如何实现此算法。请注意,这会进入一个无休止的反向引用循环(
var a={};a.a=a}

功能子模块(大、小){
if(typeof big==“function”)返回small==big;//函数引用相等。
if(big.length){//iterable,例如数组、节点列表等(偶数字符串!)
如果(small.length>big.length)返回false;//small越大!
对于(变量i=0;i
只需递归检查:

function isContainedIn(a, b) {
    if (typeof a != typeof b)
        return false;
    if (Array.isArray(a) && Array.isArray(b)) {
        // assuming same order at least
        for (var i=0, j=0, la=a.length, lb=b.length; i<la && j<lb;j++)
            if (isContainedIn(a[i], b[j]))
                i++;
        return i==la;
    } else if (Object(a) === a) {
        for (var p in a)
            if (!(p in b && isContainedIn(a[p], b[p])))
                return false;
        return true;
    } else
        return a === b;
}
对于更像集合逻辑的数组方法,顺序无关紧要,添加如下内容

        a.sort();
        b = b.slice().sort()
(假设可订购的内容)在数组比较循环之前,或者用非常低效的

        return a.every(function(ael) {
            return b.some(function(bel) {
                return isContainedIn(ael, bel);
            });
        });

//当对象的顺序不同时

function isContainedIn(a, b) {
    if (typeof a != typeof b)
        return false;
    if (Array.isArray(a) && Array.isArray(b)) {
        if(a.length == 1) {
            var j=0;
            while (j < b.length) {
                if ((isContainedIn( a[0], b[j]))) {
                    return true;
                }
                j++;
            }
            return false;
        } else {
            var k=0;
            while (k < a.length) {
                if (!(isContainedIn([a[k]], b))) {
                    return false;
                }
                k++;
            }
            return true;
        }
    } else if (Object(a) === a) {
        for (var p in a)
            if (!(p in b && isContainedIn(a[p], b[p])))
                return false;
        return true;
    } else
        return a === b;
};


isContainedIn(requirements, person)
true
函数包含在(a,b)中{
if(a的类型!=b的类型)
返回false;
if(Array.isArray(a)和&Array.isArray(b)){
如果(a.length==1){
var j=0;
而(j
除了Benjamin的答案之外,您还可以测试:

const sub = (big, small) => {
    if (typeof big === 'function' || typeof small === 'string') return small === big; // function or string reference equality
    if (big && big.length) { // iterable, for example array, nodelist etc. (even string!)
        if (small.length > big.length) return false; // small is bigger!
        for (let i = 0; i < small.length; i++)
            if (!sub(big[i], small[i])) // doesn't have a property
                return false;
        return true; // all properties are subproperties recursively
    }
    if (typeof big === 'object' && big !== null) {
        // I assume null is not a subset of an object, you may change this, it's conceptual
        if (typeof small !== 'object' || small === null) return false;
        // console.log(Object.keys(small));
        for (const key of Object.keys(small)) {
            // I consider the prototype a part of the object, you may filter this with a
            // hasOwnProperty check here.
            if (sub(big[key], small[key]) === false) // doesn't have a property
                return false;
            continue;
        }
        return true;
    }
    return big === small; // primitive value type equality
};
const sub=(大,小)=>{
if(typeof big=='function'| | typeof small=='string')返回small=='big;//函数或字符串引用相等
if(big&&big.length){//iterable,例如数组、节点列表等(偶数字符串!)
如果(small.length>big.length)返回false;//small越大!
for(设i=0;ifunction isContainedIn(a, b) {
    if (typeof a != typeof b)
        return false;
    if (Array.isArray(a) && Array.isArray(b)) {
        if(a.length == 1) {
            var j=0;
            while (j < b.length) {
                if ((isContainedIn( a[0], b[j]))) {
                    return true;
                }
                j++;
            }
            return false;
        } else {
            var k=0;
            while (k < a.length) {
                if (!(isContainedIn([a[k]], b))) {
                    return false;
                }
                k++;
            }
            return true;
        }
    } else if (Object(a) === a) {
        for (var p in a)
            if (!(p in b && isContainedIn(a[p], b[p])))
                return false;
        return true;
    } else
        return a === b;
};


isContainedIn(requirements, person)
true
const sub = (big, small) => {
    if (typeof big === 'function' || typeof small === 'string') return small === big; // function or string reference equality
    if (big && big.length) { // iterable, for example array, nodelist etc. (even string!)
        if (small.length > big.length) return false; // small is bigger!
        for (let i = 0; i < small.length; i++)
            if (!sub(big[i], small[i])) // doesn't have a property
                return false;
        return true; // all properties are subproperties recursively
    }
    if (typeof big === 'object' && big !== null) {
        // I assume null is not a subset of an object, you may change this, it's conceptual
        if (typeof small !== 'object' || small === null) return false;
        // console.log(Object.keys(small));
        for (const key of Object.keys(small)) {
            // I consider the prototype a part of the object, you may filter this with a
            // hasOwnProperty check here.
            if (sub(big[key], small[key]) === false) // doesn't have a property
                return false;
            continue;
        }
        return true;
    }
    return big === small; // primitive value type equality
};