diff-obj
Version:
101 lines (83 loc) • 2.1 kB
JavaScript
'use strict';
const is = require('is');
const extend = require('extend');
function diff(from, to, options) {
if (!is.object(from) || !is.object(to)) {
throw new Error('参数 from 或 to 未定义');
}
// 当 options 不存在,则给她个初始对象
if (!options) {
options = {
added: {},
removed: {},
changed: {},
unchanged: {},
prefix: null,
};
}
const {added, removed, changed, unchanged, prefix} = options;
for (let key in from) {
let value1 = from[key];
let value2 = to[key];
const value = {
from: value1,
to: value2,
};
// 如果两个值都是数组,则需要转为 JSON 进行比较
if (is.array(value1) && is.array(value2)) {
value1 = JSON.stringify(value1);
value2 = JSON.stringify(value2);
}
if (value1 === value2) {
unchange(key, value, options);
} else if (is.defined(value1) && is.undef(value2)) {
remove(key, value, options);
} else if (is.object(value1) && is.object(value2)) {
diff(value1, value2, extend({}, options, {
prefix: join(prefix, key),
}));
} else {
change(key, value, options);
}
}
for (let key in to) {
const value1 = from[key];
const value2 = to[key];
const value = {
from: value1,
to: value2,
};
if (is.undef(value1) && is.defined(value2)) {
add(key, value, options);
}
}
return {
added,
removed,
changed,
unchanged,
};
}
function join(key1, key2) {
if (!key1) {
return key2;
}
return [key1, key2].join('.');
}
function add(key, value, options) {
const {added, prefix} = options;
added[join(prefix, key)] = value;
}
function remove(key, value, options) {
const {removed, prefix} = options;
removed[join(prefix, key)] = value;
}
function change(key, value, options) {
const {changed, prefix} = options;
changed[join(prefix, key)] = value;
}
function unchange(key, value, options) {
const {unchanged, prefix} = options;
unchanged[join(prefix, key)] = value;
}
module.exports = diff;