-
Notifications
You must be signed in to change notification settings - Fork 479
/
diff.js
101 lines (96 loc) · 3.78 KB
/
diff.js
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
const ARRAYTYPE = '[object Array]'
const OBJECTTYPE = '[object Object]'
const FUNCTIONTYPE = '[object Function]'
export default function diff(current, pre) {
const result = {}
syncKeys(current, pre)
_diff(current, pre, '', result)
return result
}
function syncKeys(current, pre) {
if (current === pre) return
const rootCurrentType = type(current)
const rootPreType = type(pre)
if (rootCurrentType == OBJECTTYPE && rootPreType == OBJECTTYPE) {
//if(Object.keys(current).length >= Object.keys(pre).length){
for (let key in pre) {
const currentValue = current[key]
if (currentValue === undefined) {
current[key] = null
} else {
syncKeys(currentValue, pre[key])
}
}
//}
} else if (rootCurrentType == ARRAYTYPE && rootPreType == ARRAYTYPE) {
if (current.length >= pre.length) {
pre.forEach((item, index) => {
syncKeys(current[index], item)
})
}
}
}
function _diff(current, pre, path, result) {
if (current === pre) return
const rootCurrentType = type(current)
const rootPreType = type(pre)
if (rootCurrentType == OBJECTTYPE) {
if (rootPreType != OBJECTTYPE || Object.keys(current).length < Object.keys(pre).length) {
setResult(result, path, current)
} else {
for (let key in current) {
const currentValue = current[key]
const preValue = pre[key]
const currentType = type(currentValue)
const preType = type(preValue)
if (currentType != ARRAYTYPE && currentType != OBJECTTYPE) {
if (currentValue != pre[key]) {
setResult(result, (path == '' ? '' : path + ".") + key, currentValue)
}
} else if (currentType == ARRAYTYPE) {
if (preType != ARRAYTYPE) {
setResult(result, (path == '' ? '' : path + ".") + key, currentValue)
} else {
if (currentValue.length < preValue.length) {
setResult(result, (path == '' ? '' : path + ".") + key, currentValue)
} else {
currentValue.forEach((item, index) => {
_diff(item, preValue[index], (path == '' ? '' : path + ".") + key + '[' + index + ']', result)
})
}
}
} else if (currentType == OBJECTTYPE) {
if (preType != OBJECTTYPE || Object.keys(currentValue).length < Object.keys(preValue).length) {
setResult(result, (path == '' ? '' : path + ".") + key, currentValue)
} else {
for (let subKey in currentValue) {
_diff(currentValue[subKey], preValue[subKey], (path == '' ? '' : path + ".") + key + '.' + subKey, result)
}
}
}
}
}
} else if (rootCurrentType == ARRAYTYPE) {
if (rootPreType != ARRAYTYPE) {
setResult(result, path, current)
} else {
if (current.length < pre.length) {
setResult(result, path, current)
} else {
current.forEach((item, index) => {
_diff(item, pre[index], path + '[' + index + ']', result)
})
}
}
} else {
setResult(result, path, current)
}
}
function setResult(result, k, v) {
if (type(v) != FUNCTIONTYPE) {
result[k] = v
}
}
function type(obj) {
return Object.prototype.toString.call(obj)
}