检查对象数组是否已更改

3

我有一个可能包含对象的数组。对象可以添加到它中或修改属性。我想检查数组是否发生了任何变化(可能是添加了元素或仅仅是一个对象有一个键值被修改),然后根据潜在的变化更新数据库。

只是想知道我的方法是否能涵盖所有情况,或者有没有更好的方法。

const origArrayCopy = JSON.stringify(origArray);

someFnThatPotentiallyChanges(origArray);

if (origArrayCopy !== JSON.stringify(origArray)) {
    updateDB(arr);
} else {
    console.log('NO DIFF');
}

以下是我创建的 jsFiddle 测试链接 https://jsfiddle.net/j4eqwmp6/

使用 stringify 将对象转成字符串应该可以处理嵌套深度变化,对此有什么见解?还有更好的实现方式吗?


2
JSON.stringify() 可能会展示出有变化,即使实际上没有改变,因为元素的顺序发生了变化。 - Barmar
有很多种方式可能会失败。 - Pointy
1
我认为,通过一系列的添加/删除操作,使得数组中的对象以不同的顺序存在,或者通过一系列的对象属性更改,使得对象具有相同的属性但是迭代顺序不同,这种情况应该非常罕见。由于目的是决定是否进行数据库更新,一些罕见的误判可能比检查无序相等性的效率较低的算法更好。我的观点是,对于这个任务,JSON.stringify 应该是可以胜任的。 - kaya3
1
{"foo": 1, "bar": 2}{"bar": 2, "foo": 1} 是不同的 JSON,但是它们表示相同的对象。 - Barmar
1
同意 @kaya3 的观点,如果可以接受假阳性,则可以。 - Barmar
显示剩余4条评论
1个回答

1

使用JSON.stringify是一种可能性。

另一种方法是将对象(数组)包装在代理中,并对每个嵌套对象都进行这样的操作。然后捕获所有修改这些对象的行为。

以下是可能的实现方式:

function monitor(obj, cb) {
    if (Object(obj) !== obj) return obj;
    for (let key of Object.keys(obj)) {
        obj[key] = monitor(obj[key], cb);
    }
    return new Proxy(obj, {
        defineProperty(...args) {
            cb();
            return Reflect.defineProperty(...args);
        },
        deleteProperty(...args) {
            cb();
            return Reflect.deleteProperty(...args);
        },
        set(...args) {
            cb();
            return Reflect.set(...args);
        }
    });
};

// Example array
let origArray = [{x: 1}, { child: { y: 1} }];

// Activate the proxy:
let dirty = false;
origArray = monitor(origArray, () => dirty = true);

// Perform a mutation
origArray[1].child.y++;

console.log(dirty); // true
console.log(origArray);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接