当前位置: 代码迷 >> 综合 >> areEqual
  详细解决方案

areEqual

热度:90   发布时间:2024-01-09 22:37:08.0

areEqual用于比较引用类型或基本类型数据是否完全相等。

 

'use strict';var aStackPool = [];
var bStackPool = [];// 完全相等比较
function areEqual(a, b) {// aStackPool、bStackPool有值时取出,通常经过一次比较后aStackPool、bStackPool存入单个空数组元素;无值时取空数组var aStack = aStackPool.length ? aStackPool.pop() : [];var bStack = bStackPool.length ? bStackPool.pop() : [];var result = eq(a, b, aStack, bStack);// 比较完成后清空aStack和bStack,仍然保持为数组形式aStack.length = 0;bStack.length = 0;// aStackPool、bStackPool存入单个空数组元素,下次比较时取出,aStackPool、bStackPool长度不会递增aStackPool.push(aStack);bStackPool.push(bStack);return result;
}function eq(a, b, aStack, bStack) {if (a === b) {// 针对某些平台`+0 !== -0`的情况return a !== 0 || 1 / a == 1 / b;}if (a == null || b == null) {// 其中一个为null或undefined时返回falsereturn false;}if (typeof a != 'object' || typeof b != 'object') {// 排除基本类型后,其中一个不是引用类型,返回falsereturn false;}var objToStr = Object.prototype.toString;var className = objToStr.call(a);if (className != objToStr.call(b)) {// 类型判断return false;}// 字符串、数值、日期对象、布尔类型、正则对象比较switch (className) {case '[object String]':return a == String(b);case '[object Number]':return isNaN(a) || isNaN(b) ? false : a == Number(b);case '[object Date]':case '[object Boolean]':return +a == +b;case '[object RegExp]':return a.source == b.source && a.global == b.global && a.multiline == b.multiline && a.ignoreCase == b.ignoreCase;}// 何种循环结构下触发???var length = aStack.length;while (length--) {if (aStack[length] == a) {return bStack[length] == b;}}// aStack、bStack将存入a、b及其子属性、子数组项,两者相等时删除该比较项aStack.push(a);bStack.push(b);var size = 0;// 数组类型比较if (className === '[object Array]') {size = a.length;// 长度不等if (size !== b.length) {return false;}// 深度比较数组项while (size--) {if (!eq(a[size], b[size], aStack, bStack)) {return false;}}} else {// 对象的构造函数不等if (a.constructor !== b.constructor) {return false;}// 通过对象的valueOf方法返回原始值比较if (a.hasOwnProperty('valueOf') && b.hasOwnProperty('valueOf')) {return a.valueOf() == b.valueOf();}// 对象属性个数是否匹配var keys = Object.keys(a);if (keys.length != Object.keys(b).length) {return false;}// 深度比较对象属性for (var i = 0; i < keys.length; i++) {if (!eq(a[keys[i]], b[keys[i]], aStack, bStack)) {return false;}}}aStack.pop();bStack.pop();return true;
}module.exports = areEqual;