Angular源码解析3——深度比较、深度克隆 发表于 2016-09-27 为什么需要深度比较、深度克隆详细内容见上一篇。简单的说是为了比较引用类型值(对象、数组)内部数据的变化以触发脏值查询。 ##深度比较 源码实现123456789101112131415161718192021222324252627282930313233343536373839404142434445function equals(o1, o2) { //对基本类型值的比较 if (o1 === o2) return true; if (o1 === null || o2 === null) return false; //对NaN特殊处理,使得NaN === NaN if (o1 !== o1 && o2 !== o2) return true; var t1 = typeof o1, t2 = typeof o2, length, key, keySet; //如果比较的值都是对象 if (t1 == t2 && t1 == 'object') { if (isArray(o1)) { if (!isArray(o2)) return false; //都是数组,遍历数组每一项 if ((length = o1.length) == o2.length) { for (key = 0; key < length; key++) { if (!equals(o1[key], o2[key])) return false; } return true; } } else if (isDate(o1)) { if (!isDate(o2)) return false; return equals(o1.getTime(), o2.getTime()); } else if (isRegExp(o1)) { if (!isRegExp(o2)) return false; return o1.toString() == o2.toString(); } else { if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2) || isDate(o2) || isRegExp(o2)) return false; keySet = createMap(); for (key in o1) { if (key.charAt(0) === '$' || isFunction(o1[key])) continue; if (!equals(o1[key], o2[key])) return false; keySet[key] = true; } for (key in o2) { if (!(key in keySet) && key.charAt(0) !== '$' && isDefined(o2[key]) && !isFunction(o2[key])) return false; } return true; } } return false;} 深度克隆 源码实现123456789101112131415161718192021function clone (obj) { var buf; if (obj instanceof Array) { buf=[]; var i=obj.length; while (i--) { buf[i]=clone(obj[i]); } return buf; } else if (obj instanceof Object) { buf={}; for (var k in obj) { buf[k]=clone(obj[k]); } return buf; } else { return obj; }}