const dataType = (data) = > {
    const type = Object.prototype.toString.call(data);
    const startIndex = type.indexOf(' ') + 1;
    return type.slice(startIndex, -1);
};
const jsonContrast = (obj1, obj2) = > {
    let flag = true;
    function compare(obj1, obj2) {
        // Array case
        const oldType = dataType(obj1);
        const newType = dataType(obj2);
        if(oldType ! == newType) { flag =false;
        } else if (oldType === 'Object') { // The object type determines whether the attribute exists
            flag = objectCompare(obj1, obj2);
        } else if (oldType === 'Array') {
            flag = arrayCompare(obj1, obj2);
        }
        if (flag === false) {
            return false;
        } else {
            return true; }}return compare(obj1, obj2);
};
// Object comparison
function objectCompare(obj1, obj2) {
    let flag = true;
    for (let [k, v] of Object.entries(obj1)) { The // method returns an array of key-value pairs for the given object's own enumerable properties
        if(! flag)break; // If flag changes to false, data differences should be broken out of the loop
        if (obj2.hasOwnProperty(k)) { // Attribute exists, check the type
            if (dataType(v) === dataType(obj2[k]) && (dataType(v) === 'Object' || dataType(v) === 'Array')) { // Object type
                flag = jsonContrast(v, obj2[k]);
            } else if(dataType(v) ! == dataType(obj2[k])) {// Other types
                flag = false; }}else {
            flag = false; }}if (flag === false) {
        return false;
    } else {
        return true; }}// Array comparison
function arrayCompare(obj1, obj2) {
    let flag = true;
    let arrFlag = true;
    let objFlag = true;
    const obj1_statistics = {
        String: 0.Number: 0.Boolean: 0.Array: 0.Object: 0
    };
    const obj2_statistics = {
        String: 0.Number: 0.Boolean: 0.Array: 0.Object: 0
    };
    const tag = ['String'.'Number'.'Boolean'.'Array'.'Object'];
    const obj1_data_arr = [];
    const obj2_data_arr = [];
    let obj1_data_obj = [];
    const obj2_data_obj = [];

    // Array comparison first compares the length
    if (obj1.length > obj2.length) {
        flag = false;
    } else {
        // Because there are multiple types of the same type in the array, and the order can be not fixed, we need to count the uniform data type of the pull data separately
        // If the data is of complex type, it needs to be done and stored for comparison. There may be more complex types of new data than old data. There may also be cases where the contents of two objects are the same, and the sequence of data is inconsistent, etc., which need to be processed separately
        for (let i in obj1) {
            const type = dataType(obj1[i]);
            ++obj1_statistics[type];
            if (type === 'Array') {
                obj1_data_arr.push(obj1[i]);
            }
            if (type === 'Object') { obj1_data_obj.push(obj1[i]); }}for (let i in obj2) {
            const type = dataType(obj2[i]);
            ++obj2_statistics[type];
            if (type === 'Array') {
                obj2_data_arr.push(obj2[i]);
            }
            if (type === 'Object') { obj2_data_obj.push(obj2[i]); }}// If the new data is less than the old data, it indicates that the data is different
        const statistics_result = tag.findIndex(t= > obj1_statistics[t] > obj2_statistics[t]);
        if (statistics_result === -1) {
obj1_data_obj = obj1_data_obj.sort((a, b) = > Object.keys(b).length - Object.keys(a).length); // To sort old data objects, the more key values, the higher the priority comparison
            arrFlag = children(obj1_data_arr, obj2_data_arr);
            objFlag = children(obj1_data_obj, obj2_data_obj);
        } else {
            flag = false; }}if(! arrFlag || ! objFlag) { flag =false;
    }
    if (flag === false) {
        return false;
    } else {
        return true; }}function children(obj1_data, obj2_data) {
    let flag = true;
    let chelidFlag = true;
    outside: for (let i = 0; i < obj1_data.length; i++) { // Add a label to the for loop to make it easier to terminate the loop internally
        for (let j = 0; j < obj2_data.length; j++) {
            if (dataType(obj1_data[i]) === dataType(obj2_data[j]) && (dataType(obj1_data[i]) === 'Array' || dataType(obj1_data[i]) === 'Object')) {
                flag = jsonContrast(obj1_data[i], obj2_data[j]);
                if (flag === true) {
                    if(obj1_data.length ! == i) { obj1_data.splice(i,1);
                        obj2_data.splice(j, 1);
                        chelidFlag = children(obj1_data, obj2_data);
                        if (chelidFlag === false) {
                            breakoutside; }}breakoutside; }}}}if (flag === false || chelidFlag === false) {
        return false;
    } else {
        return true; }}// Set json-- ready to call
var jsonA = {
    "a": { b: 2 },
    "d": [1[[], {a: 1.b: [{ d: [{ e: [{}, []]}]}, {a: 1.b: 2 }, { a: [{ b: 1}},1]]};var jsonB = {
    "a": { b: 2 },
    "d": [1[{a: [{ b: 1{}}], [],a: 1.b: [{ d: [{ e: [[], {}]}]}, {d: 1 }, { a: 1.b: 1 }, 1]]};console.log(jsonContrast(jsonA, jsonB), '????? ');

Copy the code