Angular源码解析3——深度比较、深度克隆

为什么需要深度比较、深度克隆

详细内容见上一篇。简单的说是为了比较引用类型值(对象、数组)内部数据的变化以触发脏值查询。

##深度比较 源码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
function 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;
}

深度克隆 源码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function 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;
}
}