javascript - شرح - تحميل مكتبة jquery




كيفية التحقق من وجود صفيفين متساويين مع JavaScript؟ (11)

jQuery لديه مثل هذه الطريقة للمقارنة العودية العميقة .

يمكن أن يكون فحص المساواة الصارم للأغراض العامة محليًا كما يلي:

function deepEquals(obj1, obj2, parents1, parents2) {
    "use strict";
    var i;
    // compare null and undefined
    if (obj1 === undefined || obj2 === undefined || 
        obj1 === null || obj2 === null) {
        return obj1 === obj2;
    }

    // compare primitives
    if (typeof (obj1) !== 'object' || typeof (obj2) !== 'object') {
        return obj1.valueOf() === obj2.valueOf();
    }

    // if objects are of different types or lengths they can't be equal
    if (obj1.constructor !== obj2.constructor || (obj1.length !== undefined && obj1.length !== obj2.length)) {
        return false;
    }

    // iterate the objects
    for (i in obj1) {
        // build the parents list for object on the left (obj1)
        if (parents1 === undefined) parents1 = [];
        if (obj1.constructor === Object) parents1.push(obj1);
        // build the parents list for object on the right (obj2)
        if (parents2 === undefined) parents2 = [];
        if (obj2.constructor === Object) parents2.push(obj2);
        // walk through object properties
        if (obj1.propertyIsEnumerable(i)) {
            if (obj2.propertyIsEnumerable(i)) {
                // if object at i was met while going down here
                // it's a self reference
                if ((obj1[i].constructor === Object && parents1.indexOf(obj1[i]) >= 0) || (obj2[i].constructor === Object && parents2.indexOf(obj2[i]) >= 0)) {
                    if (obj1[i] !== obj2[i]) {
                        return false;
                    }
                    continue;
                }
                // it's not a self reference so we are here
                if (!deepEquals(obj1[i], obj2[i], parents1, parents2)) {
                    return false;
                }
            } else {
                // obj2[i] does not exist
                return false;
            }
        }
    }
    return true;
};

الاختبارات:

// message is displayed on failure
// clean console === all tests passed
function assertTrue(cond, msg) {
    if (!cond) {
        console.log(msg);
    }
}

var a = 'sdf',
    b = 'sdf';
assertTrue(deepEquals(b, a), 'Strings are equal.');
b = 'dfs';
assertTrue(!deepEquals(b, a), 'Strings are not equal.');
a = 9;
b = 9;
assertTrue(deepEquals(b, a), 'Numbers are equal.');
b = 3;
assertTrue(!deepEquals(b, a), 'Numbers are not equal.');
a = false;
b = false;
assertTrue(deepEquals(b, a), 'Booleans are equal.');
b = true;
assertTrue(!deepEquals(b, a), 'Booleans are not equal.');
a = null;
assertTrue(!deepEquals(b, a), 'Boolean is not equal to null.');
a = function () {
    return true;
};
assertTrue(deepEquals(
[
    [1, 1, 1],
    [2, 'asdf', [1, a]],
    [3, {
        'a': 1.0
    },
    true]
], 
[
    [1, 1, 1],
    [2, 'asdf', [1, a]],
    [3, {
        'a': 1.0
    },
    true]
]), 'Arrays are equal.');
assertTrue(!deepEquals(
[
    [1, 1, 1],
    [2, 'asdf', [1, a]],
    [3, {
        'a': 1.0
    },
    true]
],
[
    [1, 1, 1],
    [2, 'asdf', [1, a]],
    [3, {
        'a': '1'
    },
    true]
]), 'Arrays are not equal.');
a = {
    prop: 'val'
};
a.self = a;
b = {
    prop: 'val'
};
b.self = a;
assertTrue(deepEquals(b, a), 'Immediate self referencing objects are equal.');
a.prop = 'shmal';
assertTrue(!deepEquals(b, a), 'Immediate self referencing objects are not equal.');
a = {
    prop: 'val',
    inside: {}
};
a.inside.self = a;
b = {
    prop: 'val',
    inside: {}
};
b.inside.self = a;
assertTrue(deepEquals(b, a), 'Deep self referencing objects are equal.');
b.inside.self = b;
assertTrue(!deepEquals(b, a), 'Deep self referencing objects are not equeal. Not the same instance.');
b.inside.self = {foo: 'bar'};
assertTrue(!deepEquals(b, a), 'Deep self referencing objects are not equal. Completely different object.');
a = {};
b = {};
a.self = a;
b.self = {};
assertTrue(!deepEquals(b, a), 'Empty object and self reference of an empty object.');

هذا السؤال لديه بالفعل إجابة هنا:

var a = [1, 2, 3];
var b = [3, 2, 1];
var c = new Array(1, 2, 3);

alert(a == b + "|" + b == c);

demo

كيف يمكنني التحقق من هذه الصفوف للمساواة والحصول على الطريقة التي ترجع true إذا كانت متساوية؟

هل تقدم jQuery أي طريقة لهذا؟


إذا كنت ترغب في التحقق من صفائف الأشياء للمساواة والنظام لا يهم ، أي

areEqual([{id: "0"}, {id: "1"}], [{id: "1"}, {id: "0"}]) // true

سترغب في فرز المصفوفات أولاً. لدى lodash جميع الأدوات التي ستحتاجها ، من خلال الجمع بين sortBy و isEqual :

// arr1 & arr2: Arrays of objects 
// sortProperty: the property of the object with which you want to sort
// Note: ensure every object in both arrays has your chosen sortProperty
// For example, arr1 = [{id: "v-test_id0"}, {id: "v-test_id1"}]
// and          arr2 = [{id: "v-test_id1"}, {id: "v-test_id0"}]
// sortProperty should be 'id'

function areEqual (arr1, arr2, sortProperty) {
  return _.areEqual(_.sortBy(arr1, sortProperty), _.sortBy(arr2, sortProperty))
}

تحرير: منذ sortBy بإرجاع مجموعة جديدة ، ليست هناك حاجة لاستنساخ المصفوفات الخاصة بك قبل الفرز. لن يتم تغيير الصفائف الأصلية.

لاحظ أنه بالنسبة لـ isEqual ، لا يهم الأمر . سوف يعرض المثال أعلاه false إذا لم يتم تطبيق sortBy على كل صفيف أولاً.


استنادًا إلى answer تيم جيمس وتعليق Fox32 ، يجب أن يتحقق ما يلي من أخطاء فارغة ، بافتراض عدم وجود قيمتين فارغتين.

function arrays_equal(a,b) { return !!a && !!b && !(a<b || b<a); }

> arrays_equal([1,2,3], [1,3,4])
false
> arrays_equal([1,2,3], [1,2,3])
true
> arrays_equal([1,3,4], [1,2,3])
false
> arrays_equal(null, [1,2,3])
false
> arrays_equal(null, null)
false

التعامل مع كل الأشياء الممكنة وحتى الإشارة نفسها في بنية الكائن. يمكنك رؤية المثال في نهاية الرمز.

var deepCompare = (function() {
    function internalDeepCompare (obj1, obj2, objects) {
        var i, objPair;

        if (obj1 === obj2) {
            return true;
        }

        i = objects.length;
        while (i--) {
            objPair = objects[i];
            if (  (objPair.obj1 === obj1 && objPair.obj2 === obj2) ||
                  (objPair.obj1 === obj2 && objPair.obj2 === obj1)  ) {                          
                return true;
            }                    
        }
        objects.push({obj1: obj1, obj2: obj2});

        if (obj1 instanceof Array) {
            if (!(obj2 instanceof Array)) {
                return false;
            }

            i = obj1.length;

            if (i !== obj2.length) {
               return false; 
            }

            while (i--) {
                if (!internalDeepCompare(obj1[i], obj2[i], objects)) {
                    return false;
                }
            }
        }
        else {
            switch (typeof obj1) {
                case "object":                
                    // deal with null
                    if (!(obj2 && obj1.constructor === obj2.constructor)) {
                        return false;
                    }

                    if (obj1 instanceof RegExp) {
                        if (!(obj2 instanceof RegExp && obj1.source === obj2.source)) {
                            return false;
                        }
                    }                 
                    else if (obj1 instanceof Date) {
                        if (!(obj2 instanceof Date && obj1.getTime() === obj2.getTime())) {
                            return false;
                        }
                    } 
                    else {    
                        for (i in obj1) {
                            if (obj1.hasOwnProperty(i)) {       
                                if (!(obj2.hasOwnProperty(i) && internalDeepCompare(obj1[i], obj2[i], objects))) {
                                    return false;
                                }
                            }
                        }         
                    }
                    break;
                case "function": 
                    if (!(typeof obj2 === "function" && obj1+"" === obj2+"")) {
                        return false;
                    }
                    break;
                default:                 //deal with NaN 
                    if (obj1 !== obj2 && obj1 === obj1 && obj2 === obj2) {
                        return false;            
                    }
            }
        }

        return true;
    }

    return function (obj1, obj2) {
        return internalDeepCompare(obj1, obj2, []);    
    };
}());

/*    
var a = [a, undefined, new Date(10), /.+/, {a:2}, function(){}, Infinity, -Infinity, NaN, 0, -0, 1, [4,5], "1", "-1", "a", null],
    b = [b, undefined, new Date(10), /.+/, {a:2}, function(){}, Infinity, -Infinity, NaN, 0, -0, 1, [4,5], "1", "-1", "a", null];
deepCompare(a, b);
*/

بالنسبة للقيم البدائية مثل الأرقام والسلاسل ، يعد هذا الحل سهلاً:

a = [1,2,3]

b = [3,2,1]

a.sort().toString() == b.sort().toString() 

ستضمن الدعوة إلى sort() أن ترتيب العناصر لا يهم. ستقوم استدعاء toString() بإنشاء سلسلة بقيم مفصولة بفاصلة بحيث يمكن اختبار كلا السلاسل من أجل المساواة.


تحقق من كل قيمة من خلال حلقة for بمجرد التحقق من حجم الصفيف.

function equalArray(a, b) {
    if (a.length === b.length) {
        for (var i = 0; i < a.length; i++) {
            if (a[i] !== b[i]) {
                return false;
            }
        }
        return true;
    } else {
        return false;
    }
}

لا يوجد طريقه سهله لفعل ذلك. كنت بحاجة لذلك أيضاً ، لكني أردت وظيفة يمكنها أن تأخذ أي متغيرين واختبار للمساواة. يتضمن القيم غير الكائن والكائنات والصفائف وأي مستوى من التعشيش.

في سؤالك ، تشير إلى الرغبة في تجاهل ترتيب القيم في مصفوفة. الحل الخاص بي لا يقوم بذلك بطبيعته ، ولكن يمكنك تحقيقه عن طريق فرز المصفوفات قبل المقارنة بالمساواة

أردت أيضًا خيار صب الأشياء غير السلاسل حتى [1،2] === ["1" ، 2]

بما أن مشروعي يستخدم UnderscoreJs ، فقد قررت أن أجعله مزيجًا بدلاً من وظيفة مستقلة.

يمكنك اختبار ذلك على http://jsfiddle.net/nemesarial/T44W4/

هنا هو بلدي mxin:

_.mixin({
  /**
  Tests for the equality of two variables
    valA: first variable
    valB: second variable
    stringifyStatics: cast non-objects to string so that "1"===1
  **/
  equal:function(valA,valB,stringifyStatics){
    stringifyStatics=!!stringifyStatics;

    //check for same type
    if(typeof(valA)!==typeof(valB)){
      if((_.isObject(valA) || _.isObject(valB))){
        return false;
      }
    }

    //test non-objects for equality
    if(!_.isObject(valA)){
      if(stringifyStatics){
        var valAs=''+valA;
        var valBs=''+valB;
        ret=(''+valA)===(''+valB);
      }else{
        ret=valA===valB;
      }
      return ret;
    }

    //test for length
    if(_.size(valA)!=_.size(valB)){
      return false;
    }

    //test for arrays first
    var isArr=_.isArray(valA);

    //test whether both are array or both object
    if(isArr!==_.isArray(valB)){
      return false;
    }

    var ret=true;
    if(isArr){
      //do test for arrays
      _.each(valA,function(val,idx,lst){
        if(!ret){return;}
        ret=ret && _.equal(val,valB[idx],stringifyStatics);
      });
    }else{
      //do test for objects
      _.each(valA,function(val,idx,lst){
        if(!ret){return;}

        //test for object member exists
        if(!_.has(valB,idx)){
          ret=false;
          return;
        }

        // test for member equality
        ret=ret && _.equal(val,valB[idx],stringifyStatics);
      });

    }
    return ret;
  }
});

هذه هي الطريقة التي تستخدمها:

_.equal([1,2,3],[1,2,"3"],true)

لإظهار التعشيش ، يمكنك القيام بذلك:

_.equal(
    ['a',{b:'b',c:[{'someId':1},2]},[1,2,3]],
    ['a',{b:'b',c:[{'someId':"1"},2]},["1",'2',3]]
,true);

ليس لدى jQuery طريقة لمقارنة المصفوفات. ومع ذلك ، فإن مكتبة Underscore (أو مكتبة Lodash المماثلة) لديها مثل هذه الطريقة: isEqual ، ويمكنها التعامل مع مجموعة متنوعة من الحالات الأخرى (مثل حرفية الكائن). للتشبث بالمثال المقدم:

var a=[1,2,3];
var b=[3,2,1];
var c=new Array(1,2,3);

alert(_.isEqual(a, b) + "|" + _.isEqual(b, c));

بالمناسبة: تحتل Underscore الكثير من الطرق الأخرى التي تفتقدها jQuery أيضًا ، لذا فهي مكملة رائعة لـ jQuery.

تحرير: كما هو موضح في التعليقات ، ما ورد أعلاه الآن يعمل فقط إذا كان كلا المصفوفات عناصرها في نفس الترتيب ، أي:

_.isEqual([1,2,3], [1,2,3]); // true
_.isEqual([1,2,3], [3,2,1]); // false

لحسن الحظ ، تحتوي Javascript على طريقة مضمنة لحل هذه المشكلة بالتحديد ، sort :

_.isEqual([1,2,3].sort(), [3,2,1].sort()); // true

هذا هو ما يجب عليك القيام به. من فضلك لا تستخدم stringify ولا < > .

function arraysEqual(a, b) {
  if (a === b) return true;
  if (a == null || b == null) return false;
  if (a.length != b.length) return false;

  // If you don't care about the order of the elements inside
  // the array, you should sort both arrays here.

  for (var i = 0; i < a.length; ++i) {
    if (a[i] !== b[i]) return false;
  }
  return true;
}

الخيار 1

الخيار الأسهل ، يعمل في جميع الحالات تقريبًا ، ما عدا ذلك null ! == undefined ولكن يتم تحويل كلاهما إلى تمثيل JSON null ويعتبر مساوياً:

function arraysEqual(a1,a2) {
    /* WARNING: arrays must not contain {objects} or behavior may be undefined */
    return JSON.stringify(a1)==JSON.stringify(a2);
}

( قد لا يعمل هذا إذا احتوى المصفوفة على كائنات. يعتمد ما إذا كان هذا مازال يعمل مع الكائنات على ما إذا كان تنفيذ JSON يفرز المفاتيح أم لا. على سبيل المثال ، قد يساوي JSON {1:2,3:4} أو لا يساوي {3:4,1:2} ؛ هذا يعتمد على التنفيذ ، والمواصفات لا تقدم أي ضمان على الإطلاق. [2017 update: في الواقع تضمن مواصفات ES6 الآن مفاتيح الكائن بالترتيب الذي تم إدراجه بها. إذا كانت JSON.stringify application بعد ذلك ، ستتم إضافة كائنات متساوية إلى قيم متساوية. يجب إجراء المزيد من الأبحاث.] على الأقل على Chrome ، تميل وظيفة JSON.stringify إلى إرجاع المفاتيح بالترتيب الذي تم تعريفه به (على الأقل ما لاحظته) ، ولكن هذا السلوك الخاضع للتغيير في أي نقطة ولا ينبغي الاعتماد عليه ، وإذا اخترت عدم استخدام الكائنات في قوائمك ، فيجب أن يعمل هذا بشكل جيد. إذا كان لديك كائنات في قائمتك تحتوي جميعها على معرف فريد ، فيمكنك إجراء a1.map(function(x)}{return {id:x.uniqueId}}) إذا كان لديك كائنات عشوائية في قائمتك ، يمكنك القراءة للخيار رقم 2.)

هذا يعمل للصفائف المتداخلة كذلك.

ومع ذلك ، فهي غير فعالة بعض الشيء بسبب النفقات العامة لإنشاء هذه السلاسل وجمع القمامة.

الخيار 2

خيار "مناسب" أكثر ، والذي يمكنك تجاوزه للتعامل مع الحالات الخاصة (مثل الأشياء العادية والكائنات الخالية / غير المعروفة والعرف ، إذا كنت ترغب في ذلك):

// generally useful functions
function type(x) { // does not work in general, but works on JSONable objects we care about... modify as you see fit
    // e.g.  type(/asdf/g) --> "[object RegExp]"
    return Object.prototype.toString.call(x);
}
function zip(arrays) {
    // e.g. zip([[1,2,3],[4,5,6]]) --> [[1,4],[2,5],[3,6]]
    return arrays[0].map(function(_,i){
        return arrays.map(function(array){return array[i]})
    });
}

// helper functions
function allCompareEqual(array) {
    // e.g.  allCompareEqual([2,2,2,2]) --> true
    // does not work with nested arrays or objects
    return array.every(function(x){return x==array[0]});
}

function isArray(x){ return type(x)==type([]) }
function getLength(x){ return x.length }
function allTrue(array){ return array.reduce(function(a,b){return a&&b},true) }
    // e.g. allTrue([true,true,true,true]) --> true
    // or just array.every(function(x){return x});

function allDeepEqual(things) {
    // works with nested arrays
    if( things.every(isArray) )
        return allCompareEqual(things.map(getLength))     // all arrays of same length
               && allTrue(zip(things).map(allDeepEqual)); // elements recursively equal

    //else if( this.every(isObject) )
    //  return {all have exactly same keys, and for 
    //          each key k, allDeepEqual([o1[k],o2[k],...])}
    //  e.g. ... && allTrue(objectZip(objects).map(allDeepEqual)) 

    //else if( ... )
    //  extend some more

    else
        return allCompareEqual(things);
}

عرض:

allDeepEqual([ [], [], [] ])
true
allDeepEqual([ [1], [1], [1] ])
true
allDeepEqual([ [1,2], [1,2] ])
true
allDeepEqual([ [[1,2],[3]], [[1,2],[3]] ])
true

allDeepEqual([ [1,2,3], [1,2,3,4] ])
false
allDeepEqual([ [[1,2],[3]], [[1,2],[],3] ])
false
allDeepEqual([ [[1,2],[3]], [[1],[2,3]] ])
false
allDeepEqual([ [[1,2],3], [1,[2,3]] ])
false

لاستخدام هذا مثل وظيفة عادية ، قم بما يلي:

function allDeepEqual2() {
    return allDeepEqual([].slice.call(arguments));
}

عرض:

allDeepEqual2([[1,2],3], [[1,2],3])
true

خيارات 3

تحرير : إنه عام 2016 وكانت إجابتي السابقة المعقدة تنصت لي. إن هذا التطبيق العودي "للبرمجة المتكررة العودية 101" يبقي الكود بسيطًا جدًا ، ويفشل أيضًا في أقرب نقطة ممكنة (يمنحنا الكفاءة). كما أنه لا يولد بيانات سطحية زائدة عن الحاجة (ليس هناك أي خطأ في البرمجة الوظيفية بشكل عام ، ولكن فقط إبقائها نظيفة هنا).

إذا أردنا تطبيق ذلك على صفائف غير فارغة من المصفوفات ، فيمكننا إجراء تسلسل OutRrays.reduce (arraysEqual).

هذه هي وظيفتها الخاصة ، بدلا من استخدام Object.defineProperties لإرفاق Array.prototype ، لأن ذلك من شأنه أن يفشل مع خطأ رئيسي إذا مررنا في قيمة غير محددة (وهذا هو قرار التصميم الجيد إذا كنت ترغب في القيام بذلك) .

هذا فقط يجيب على سؤال أصلي OP.

function arraysEqual(a,b) {
    /*
        Array-aware equality checker:
        Returns whether arguments a and b are == to each other;
        however if they are equal-lengthed arrays, returns whether their 
        elements are pairwise == to each other recursively under this
        definition.
    */
    if (a instanceof Array && b instanceof Array) {
        if (a.length!=b.length)  // assert same length
            return false;
        for(var i=0; i<a.length; i++)  // assert each element equal
            if (!arraysEqual(a[i],b[i]))
                return false;
        return true;
    } else {
        return a==b;  // if not both arrays, should be the same
    }
}

أمثلة:

arraysEqual([[1,2],3], [[1,2],3])
true
arraysEqual([1,2,3], [1,2,3,4])
false
arraysEqual([[1,2],[3]], [[1,2],[],3])
false
arraysEqual([[1,2],[3]], [[1],[2,3]])
false
arraysEqual([[1,2],3], undefined)
false
arraysEqual(undefined, undefined)
true
arraysEqual(1, 2)
false
arraysEqual(null, null)
true
arraysEqual(1, 1)
true
arraysEqual([], 1)
false
arraysEqual([], undefined)
false
arraysEqual([], [])
true

إذا كنت تريد تطبيق ذلك على هياكل بيانات تشبه JSON مع كائنات js ، فيمكنك القيام بذلك. لحسن الحظ أننا نضمن أن تكون جميع مفاتيح الكائنات فريدة من نوعها ، لذا قم بالتكرار فوق الكائنات OwnProperties وفرزها حسب المفتاح ، ثم أكد أن كلا من مصفوفة المفاتيح التي تم فرزها متساوية وأن متساوية القيمة متساوية ، ومجرد تكراري. يمكننا توسيع هذا ليشمل الخرائط أيضًا (حيث تكون المفاتيح فريدة أيضًا). (ومع ذلك ، إذا قمنا بتوسيع نطاق ذلك إلى مجموعات ، فإننا نواجه مشكلة تشابه الشجرة http://logic.pdmi.ras.ru/~smal/files/smal_jass08_slides.pdf - لحسن الحظ ، ليس من الصعب تحديد شكل التماثل العام ؛ يوجد في الواقع ، خوارزمية O (#vertices) لحلها ، ولكن يمكن أن تكون معقدة للغاية للقيام بذلك بكفاءة ، الحالة المرضية هي إذا كان لديك مجموعة تتكون من الكثير من الأشياء التي تبدو غير قابلة للتمييز ، ولكن عند إجراء المزيد من الفحص ، فإن بعض هذه الكائنات قد تختلف عندما تتعمق أكثر في ذلك ، ويمكنك أيضًا حل هذه المشكلة باستخدام التجزئة لرفض جميع الحالات تقريبًا.)

الخيار 4: (استمرار تعديل 2016)

يجب أن يعمل هذا مع معظم الكائنات:

function deepEquals(a,b) {
    if (a instanceof Array && b instanceof Array)
        return arraysEqual(a,b);
    if (Object.getPrototypeOf(a)===Object.prototype && Object.getPrototypeOf(b)===Object.prototype)
        return objectsEqual(a,b);
    if (a instanceof Map && b instanceof Map)
        return mapsEqual(a,b);        
    if (a instanceof Set && b instanceof Set)
        throw "Error: set equality by hashing not implemented."
    if ((a instanceof ArrayBuffer || ArrayBuffer.isView(a)) && (b instanceof ArrayBuffer || ArrayBuffer.isView(b)))
        return typedArraysEqual(a,b);
    return a==b;  // see note[1]
}

function arraysEqual(a,b) {
    if (a.length!=b.length)
        return false;
    for(var i=0; i<a.length; i++)
        if (!deepEquals(a[i],b[i]))
            return false;
    return true;
}
function objectsEqual(a,b) {
    var aKeys = Object.getOwnPropertyNames(a);
    var bKeys = Object.getOwnPropertyNames(b);
    if (aKeys.length!=bKeys.length)
        return false;
    aKeys.sort();
    bKeys.sort();
    for(var i=0; i<aKeys.length; i++)
        if (aKeys[i]!=bKeys[i]) // keys must be strings
            return false;
    return deepEquals(aKeys.map(k=>a[k]), aKeys.map(k=>b[k]));
}
function mapsEqual(a,b) {
    if (a.size!=b.size)
        return false;
    var aPairs = Array.from(a);
    var bPairs = Array.from(b);
    aPairs.sort((x,y) => x[0]<y[0]);
    bPairs.sort((x,y) => x[0]<y[0]);
    for(var i=0; i<a.length; i++)
        if (!deepEquals(aPairs[i][0],bPairs[i][0]) || !deepEquals(aPairs[i][1],bPairs[i][1]))
            return false;
    return true;
}
function typedArraysEqual(a,b) {
    a = new Uint8Array(a);
    b = new Uint8Array(b);
    if (a.length != b.length)
        return false;
    for(var i=0; i<a.length; i++)
        if (a[i]!=b[i])
            return false;
    return true;
}

العرض التوضيحي (لم يتم اختباره على نطاق واسع):

var nineTen = new Float32Array(2);
nineTen[0]=9; nineTen[1]=10;
deepEquals(
    [[1,[2,3]], 4, {a:5,b:6}, new Map([['c',7],['d',8]]), nineTen],
    [[1,[2,3]], 4, {b:6,a:5}, new Map([['d',8],['c',7]]), nineTen]
)

(sidenote: الخرائط عبارة عن قواميس es6 لا أستطيع أن أعرف ما إذا كان لديهم أداء بحث O (1) أو O (log (N)) ، ولكن في أي حال يتم "ترتيبهم" بمعنى أنهم يتتبعون حيث تم إدراج أزواج القيمة الرئيسية فيها ، ومع ذلك ، فإن الدلالة ما إذا كان اثنان من الخرائط يجب أن يكونا متساويين إذا تم إدراج عناصر في ترتيب مختلف فيها ، أمرًا غامضًا ، فأنا أعطي عينة من التنفيذ أقل من عمق. حتى لو تم إدخال العناصر في ترتيب مختلف.)

(ملاحظة [1]: قد ترغب في تجاوز الخط المرصود بمفهوم مخصص للمساواة ، والذي سيتعين عليك أيضًا تغيير الوظائف الأخرى في أي مكان يظهر فيه. ================================================================================================

يجب أن تكون قادراً على توسيع أعلاه إلى WeakMaps ، WeakSets. لست متأكدًا مما إذا كان من المنطقي التمديد إلى DataViews. يجب أن يكون أيضًا قادرًا على التمديد إلى RegExps على الأرجح ، إلخ.

كلما قمت بتمديده ، تدرك أنك تقوم بالكثير من المقارنات غير الضرورية. هذا هو المكان الذي يمكن أن تكون فيه وظيفة type التي قمت بتحديدها بطريقة مبكرة (الحل رقم 2) مفيدة. ثم يمكنك إرسالها على الفور. ما إذا كان ذلك يستحق النفقات العامة (ربما؟ غير متأكد كيف يعمل تحت غطاء محرك السيارة) سلسلة تمثل نوع ما متروك لك. يمكنك بعد ذلك فقط إعادة كتابة المرسل ، أي وظيفة deepEquals ، ليكون شيء مثل:

var dispatchTypeEquals = {
    number: function(a,b) {...a==b...},
    array: function(a,b) {...deepEquals(x,y)...},
    ...
}
function deepEquals(a,b) {
    var typeA = extractType(a);
    var typeB = extractType(a);
    return typeA==typeB && dispatchTypeEquals[typeA](a,b);
}

var a= [1, 2, 3, '3'];
var b = [1, 2, 3];

var c = a.filter(function (i) { return ! ~b.indexOf(i); });

alert(c.length);




jquery