js对象优化函数?

function deepProxy(target, path = []) {
        const changedValues = {};
        const handler = (path) => ({
            set: function (obj, prop, value) {
                console.log(`属性 ${prop} 被设置为 ${value}`);
                obj[prop] = value;
                setChangedValue(changedValues, [...path, prop], value);
                return true;
            },
            get: function (obj, prop) {
                if (typeof obj[prop] === "object" && obj[prop] !== null) {
                    // 处理数组
                    if (Array.isArray(obj[prop])) {
                        return new Proxy(obj[prop], arrayHandler([...path, prop]));
                    }
                    // 处理对象
                    return new Proxy(obj[prop], handler([...path, prop]));
                }
                return obj[prop];
            },
        });
        const arrayHandler = (path) => ({
            set: function (obj, prop, value) {
                console.log(`属性 ${prop} 被设置为 ${value}`);
                obj[prop] = value;
                if (!isNaN(prop)) {
                    setChangedValue(changedValues, [...path, prop], obj.slice());
                }
                return true;
            },
            get: function (obj, prop) {
                if (typeof obj[prop] === "object" && obj[prop] !== null) {
                    // 处理数组
                    if (Array.isArray(obj[prop])) {
                        return new Proxy(obj[prop], arrayHandler([...path, prop]));
                    }
                    // 处理对象
                    return new Proxy(obj[prop], handler([...path, prop]));
                }
                return obj[prop];
            },
        });

        const proxy = new Proxy(target, handler(path));

        return {
            proxy,
            changedValues,
        };
    }

    function setChangedValue(obj, path, value) {
        const lastIndex = path.length - 1;
        for (let i = 0; i < lastIndex; i++) {
            const prop = path[i];
            if (!(prop in obj)) {
                obj[prop] = typeof path[i + 1] === "number" ? [] : {};
            }
            obj = obj[prop];
        }
        obj[path[lastIndex]] = value;
    }

    const obj = {
        a: 1,
        b: {
            c: 2,
            d: {
                e: 3,
            },
        },
        f: [4, 5, {g: 6}],
    };


    const {proxy, changedValues} = deepProxy(obj);

    proxy.a = 7;
    proxy.b.c = 8;
    proxy.b.d.e = 9;
    proxy.f[0] = 10;
    proxy.f[2].g = 11;

   console.log(changedValues)

生成结果

{
    "a": 7,
    "b": {
        "c": 8,
        "d": {
            "e": 9
        }
    },
    "f": {
        "0": [
            10,
            5,
            {
                "g": 11
            }
        ],
        "2": {
            "g": 11
        }
    }
}

多生成了一个{g:11}

期望结果

    const obj1 = {
        a: 7,
        b: {
            c: 8,
            d: {
                e: 3,
            },
        }, f: [10, 5, {g: 11}],

    }
阅读 1.4k
1 个回答

您好,楼主,您在最开始的时候设置了一个setChangedValue 函数,根据前面代码的含义,你应该是想对这个变化值进行记录
图片.png

但是在后面的代码中,在处理对象类型属性时,没有看到进行类似操作。因为你没有进行深拷贝处理,导致最终生成结果中多出了一个{g:11}。这里我用一张图描述下深拷贝浅拷贝区别
d9862c00-69b8-11eb-ab90-d9ae814b240d.png

因此要解决这个问题,你可以试试JSON.parse(JSON.stringify()) 方法进行转换,并将转换后
的值存储到变化记录对象中。这样可以保证记录对象和原始数据之间不存在引用关系,避免互相影响。因此应该在你的代码基础上简单修改下(示例代码已本地测试正常):

const arrayHandler = (path) => ({
set: function (obj, prop, value) {
console.log(属性 ${prop} 被设置为 ${value});
obj[prop] = value;
if (!isNaN(prop)) {
const copiedObj = JSON.parse(JSON.stringify(obj));
setChangedValue(changedValues, [...path, prop], copiedObj);
}
return true;
},
get: function (obj, prop) {
if (typeof obj[prop] === "object" && obj[prop] !== null) {
// 处理数组
if (Array.isArray(obj[prop])) {
return new Proxy(obj[prop], arrayHandler([...path, prop]));
}
// 处理对象
return new Proxy(obj[prop], handler([...path, prop]));
}
return obj[prop];
},
});

修改后就可以正常运行且不会多一个值了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Microsoft
子站问答
访问
宣传栏