Underscore库的isEqual函数分析
JavaScript Underscore发表于2017年09月18日13:44:25
0条评论 248次阅读
var eq = function(a, b, aStack, bStack) {
//三等走这个逻辑。有个东西特殊0和-0,是三等的。但我们认为不是相等的
//因为1/0 ===Infinity 而1/-0===-Infinity,所以我们认为0是不等于-0的
//注意此if是三等来判断的。能返回true,值必然相等。
if (a === b) return a !== 0 || 1 / a === 1 / b;
// 对undefined做了一下保障(但个人觉得上面if已经够用)
if (a == null || b == null) return a === b;
// 如果a或b是_的实例。比较的是其包裹_wrapped对象
if (a instanceof _) a = a._wrapped;
if (b instanceof _) b = b._wrapped;
//获取a,b的类型
var className = toString.call(a);
//如果类型不等,直接返回false
if (className !== toString.call(b)) return false;
//类型相等的话,进一步,根据类型采取不同的处理
switch (className) {
case '[object RegExp]':
case '[object String]':
//正则转化成字符串来比较因为''+/a/i==='/a/i'为true的
//字符串new String("a")===new String("a")为false,但我们认为是相等。值比较嘛。
return '' + a === '' + b;
case '[object Number]':
//这里主要针对NaN请。NaN虽然不等于自身。但是我们认为它是值相等的
//如果下面+a !== +a为true。说明a是NaN.+表示转化数字
//如果+b !== +b为true说明b也是NaN,所以a,b值相等
//如果+b !== +b为false说明b不是NaN,自然a和b不等
if (+a !== +a) return +b !== +b;
//如果不是NaN,也要考虑0的情况
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
case '[object Date]':
case '[object Boolean]':
//日期和布尔值也转化数字来比较。日期转化数字,得到的是毫秒数
return +a === +b;
}
var areArrays = className === '[object Array]';
//如果不是数组
if (!areArrays) {
//只要有一个不是Object类型。则认为不等
if (typeof a != 'object' || typeof b != 'object') return false;
var aCtor = a.constructor, bCtor = b.constructor;
//如果构造函数不等也返回false。但是有种情况除在外
//Object类型和Array的,
//即使属于不同iframe的,如果值一样。我们也认为是相等的
//不同iframe下的同样的对象 ===判断是不等的。
//Object instanceof Object为true的
if (aCtor !== bCtor
&& !(_.isFunction(aCtor)
&& aCtor instanceof aCtor
&&_.isFunction(bCtor)
&& bCtor instanceof bCtor)
&& ('constructor' in a && 'constructor' in b)) {
return false;
}
}
aStack = aStack || [];
bStack = bStack || [];
var length = aStack.length;
while (length--) {
/**自嵌套结构判断,如下面的a
*var a = {name : '11'};
*a.o = a;
*var c = a.o;
*alert(c.name);
*/
//如果a有嵌套现象,就看看b是否也有,注意a有,就返回了
if (aStack[length] === a) return bStack[length] === b;
}
//如果上面while中没有进if,这里把a和b放到栈里
aStack.push(a);
bStack.push(b);
// 如果是数组
if (areArrays) {
length = a.length;
//如果长度不等,直接返回false
if (length !== b.length) return false;
//递归比较每个元素
while (length--) {
//有一个元素不等,就返回false
if (!eq(a[length], b[length], aStack, bStack)) return false;
}
} else {
//如果是对象
var keys = _.keys(a), key;
length = keys.length;
//看看对象的键数目是否相等,不是直接返回
if (_.keys(b).length !== length) return false;
//递归比较每个属性值是否相等
while (length--) {
key = keys[length];
//首先属性名称都得有,然看值是否相等,不等就返回false
if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
}
}
//移除栈里最新的元素。说明这层是相等的
aStack.pop();
bStack.pop();
return true;
};
来源:
http://www.css88.com/doc/underscore/docs/underscore.html
http://www.qdfuns.com/notes/17398/a26d87c5c48225143cbcd43540e3a7a5.html
👍 0 👎 0
共有0条评论