Proxy的不可变数据优点及使用详解

2023-03-02 16:04:31
目录
可变数据不可变数据(Immutable Data)优点实现一:独立方法实现二:自定义对象实现三:函数 + 复制实现四:Proxy代理实现五:第三方不可变对象

可变数据

    对象被赋值后,更改对象,两个都会改变,因为其引用着相同的地址,我们称这为可变对象所以这会造成意想不到的修改React>

    不可变数据(Immutable>
      Immutable.js 中 对 Immutable 对象 增删改查都会返回一个全新的 Immutable 对象,保证旧数据的可用不变Immutable 使用了结构共享,即对象树中的节点改变只会影响自己和其父节点,其他节点共享

      优点

        保护数据意外更改,减少bug方便跟踪数据变更,便于排错

        实现一:独立方法

          调用麻烦
          function updateData(obj, key, value) {
            return {
              ...obj,
              [key]: value
            };
          }
          const obj = {
            name: "云牧"
          };
          const newObj = updateData(obj, "name", "黛玉");
          console.log(newObj); // { name: '黛玉' }
          console.log(obj); // { name: '云牧' }
          

          实现二:自定义对象

            自定义新的对象类型,对其操作细节封装在其内部著名的>immutable-js,就是这个思路,定义了ListStackMapOrderedMapSetOrderedSetRecord 这么多对象
            class MyObject {
              constructor(obj = {}) {
                this.obj = { ...obj };
              }
              get(name) {
                return this.obj[name];
              }
              set(name, value) {
                return new MyObject({
                  ...this.obj,
                  [name]: value
                });
              }
            }
            const obj = new MyObject({
              name: "云牧"
            });
            const newObj = obj.set("name", "黛玉");
            console.log(newObj); // MyObject { obj: { name: '黛玉' } }
            console.log(obj); // MyObject { obj: { name: '云牧' } }
            

            实现三:函数>
              函数调用产生新对象,对其新对象操作之后返回性能损耗比较大
              function produce(obj, recipe) {
                const newObj = { ...obj };
                recipe(newObj);
                return newObj;
              }
              const obj = {
                name: "云牧"
              };
              const newObj = produce(obj, draft => {
                draft.name = "黛玉";
              });
              console.log(newObj); // { name: '黛玉' }
              console.log(obj); // { name: '云牧' }
              

              实现四:Proxy代理

              function produce(obj, recipe) {
                const state = {
                  base: obj, // 基础对象
                  copy: {}, // 被更改后的对象
                  draft: {}, // 代理对象
                  currentKey: 0 // 当前操作的key
                };
                const handlerItem = {
                  get(target, property, receiver) {
                    // 如果更改后的对象存在则使用copy
                    if (state.copy[state.currentKey]) {
                      return state.copy[state.currentKey][property];
                    }
                    return state.base[state.currentKey][property];
                  },
                  set(target, property, value, receiver) {
                    Reflect.set(state.copy[state.currentKey], property, value);
                  }
                };
                const handler = {
                  get(target, property, receiver) {
                    state.currentKey = property;
                    if (!state.draft[property]) {
                      const val = { ...state.base[property] };
                      const proxy = new Proxy(val, handlerItem);
                      state.draft[property] = proxy;
                      state.copy[property] = val;
                    }
                    return state.draft[property];
                  },
                  set(target, property, value, receiver) {
                    return Reflect.set(state.copy, property, value);
                  }
                };
                const proxyObj = new Proxy(obj, handler);
                recipe(proxyObj);
                return proxyObj;
              }
              const arrObj = Array.from({ length: 100 }, (v, index) => ({ name: "云牧" + index }));
              const newObj = produce(arrObj, draft => {
                draft[50].name = "黛玉";
              });
              console.log(newObj[50].name); // 黛玉
              console.log(arrObj[50].name); // 云牧50
              

              实现五:第三方不可变对象

                JS没有不可变结构,我们一般可以使用>Immutable.js 和 immerjsImmutable.js 需要学习他的数据格式操作,且其不可变数据需要 toJS 才能得到原生对象,心智负担大immerjs 则没有这方面的问题,且体积更为小巧

                以上就是Proxy的不可变数据优点及使用详解的详细内容,更多关于Proxy不可变数据的资料请关注易采站长站其它相关文章!