如果有如下两个对象数组:
let arr1 = [{a: 1}, {b: 2}]
let arr2 = [{a: 1}, {b: 2}]
怎么判断它们是否相等呢?
相等有两种情况:
1、完全相等;(包含顺序相同)
2、仅元素相等;(顺序不一定相同)
一般来说,我们讨论得比较多的时第一种情况,也就是完全相等,差一点都不行,莫说顺序不一致;
其实这种情况也最容易判断,那就是直接用JSON.stringify()方法,如下:
判断两个数组完全相等的方法:
function isEqualArray(arr1, arr2){
return Array.isArray(arr1) &&
Array.isArray(arr2) &&
arr1.length === arr2.length &&
JSON.stringify(arr1) === JSON.stringify(arr2)
}
就是这样,直接判断转成的字符串是否完全相等就可以了
判断两个数组仅元素相等的方法:
如果是普通数组,那还好判断,但对于对象数组,这个判断不太好下手,先思索一下:
第一步:长度相等;(这个判断可以提高效率)
第二步:每个对象元素相等;(这个相等,也不考虑对象属性顺序)
第三步:如果元素的属性值又是一个对象呢,则要递归判断了
第四步:如果元素的属性值是一个Function、Date、Symbol、Array呢,又要怎么判断
……
有点复杂,因此我们仅讨论Plain Object类对象(键值对),以下统一简称为对象:
首先,判断数组元素的是否相等,先要判断元素是否一个对象:
function isPlainObject(obj){
return typeof obj === 'object' && Object.prototype.toString.call(obj) === '[object Object]'
}
但这里用的话,其实直接用instanceof Object也行了;
然后判断这个对象内容是否相等,即属性是否相等:
详细过程请看链接:
/**
* @method 复杂对象对比(无序)
* @param obj1
* @property {String | Boolean| Number | Array | Object | Function | Date} obj1.*
* @param obj2
* @property {String | Boolean| Number | Array | Object | Function | Date} obj2.*
* @return {Boolean}
*/
function isEqualObject(obj1, obj2){
if( !isPlainObject(obj1) || !isPlainObject(obj2) ){
return obj1 === obj2
}
if(getObjectLen(obj1) !== getObjectLen(obj2)){
return false
}
for(let key in obj1){
if(key === '__proto__' || obj1[key] === obj2){
continue
}
if( isPlainObject(obj1[key]) && isPlainObject(obj2[key]) ){
if(!isEqualObject(obj1[key], obj2[key])){
return false
}
}else if( isFunction(obj1[key]) && isFunction(obj2[key]) ){
//这里的方法在上面的文章里有
if(!isEqualFunction(obj1[key], obj2[key])){
return false
}
}else if(Array.isArray(obj1[key]) && Array.isArray(obj2[key])){
if(!isEqualArray(obj1[key], obj2[key])){
return false
}
}else if( isDate(obj1[key]) && isDate(obj2[key]) ){
//这里的方法在上面的文章里有
if( !isEqualDate(obj1[key], obj2[key]) ){
return false
}
}else if(obj1[key] !== obj2[key]){
return false
}
}
return true
}
再考虑下Function类型:
/**
**判断值是否为Function
*/
function isFunction( fun ){
return typeof fun === 'function' && Object.prototype.toString.call( fun ) === '[object Function]'
}
/**
**判断两个function是否相等(转为字符串做对比)
**/
function isEqualFunction( fun1, fun2){
if(!isFunction( fun1 ) || !isFunction( fun2 )){
return fun1 === fun2
}
if( String( fun1 ) !== String( fun2 )){
return false
}
return true
}
这样的话,判断两个对象数组仅元素相等的方法就出来了:
/**
* @method 两个复杂数组是否相等(有序)-- 无序的先排序再传进来
* @param {*} arr1
* @property {String | Boolean| Number | Array | Object | Function | Date} arr1[].*
* @param {*} arr2
* @property {String | Boolean| Number | Array | Object | Function | Date} arr2[].*
* @return {Boolean}
*/
function isEqualArray(arr1, arr2){
if( !Array.isArray(arr1) || !Array.isArray(arr2)){
return arr1 === arr2
}
if(arr.length !== arr2.length){
return false
}
for ( let i = 0; i < arr1.length; i++) {
if(isPlainObject(arr1[i]) && isPlainObject(arr2[i])){
if( !isEqualObject(arr1[i], arr2[i])){
return false
}
}else if(isFunction(arr1[i]) && isFunction(arr2[i])){
if( !isEqualFunction(arr1[i], arr2[i])){
return false
}
}else if(Array.isArray(arr1[i]) && Array.isArray(arr2[i])){
if( !isEqualArray(arr1[i], arr2[i])){
return false
}
}else if( isDate(arr1[i]) && isDate(arr2[i]) ){
//这里的方法在上面的文章里
if( !isEqualDate(arr1[i], arr2[i]) ){
return false
}
}else if(arr1[i] !== arr2[i]){
return false
}
}
return true
}
没想到这么复杂,但总算是写出来了,判断对象相等已经够麻烦,判断对象数组相等就更繁琐了;
好了,赶紧去试试吧