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

 更新时间:2023年03月02日 09:21:16   作者:云牧  
这篇文章主要为大家介绍了Proxy的不可变数据优点及使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

可变数据

  • 对象被赋值后,更改对象,两个都会改变,因为其引用着相同的地址,我们称这为可变对象
  • 所以这会造成意想不到的修改
  • React 要求本地组件的状态保持不可变性,Redux 同样要求全局状态保持不可变

不可变数据(Immutable Data)

  • 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.jsimmerjs
  • Immutable.js 需要学习他的数据格式操作,且其不可变数据需要 toJS 才能得到原生对象,心智负担大
  • immerjs 则没有这方面的问题,且体积更为小巧

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

相关文章

  • 微信小程序 教程之小程序配置

    微信小程序 教程之小程序配置

    这篇文章主要介绍了微信小程序 教程之小程序配置的相关资料,这里对app.json,pages,window等做了详细介绍,对于初学开发微信小程序的朋友,掌握这些还是比较重要的,需要的朋友可以参考下
    2016-10-10
  • 微信小程序 免费SSL证书https、TLS版本问题的解决办法

    微信小程序 免费SSL证书https、TLS版本问题的解决办法

    这篇文章主要介绍了微信小程序 免费SSL证书https、TLS版本问题的解决办法的相关资料,需要的朋友可以参考下
    2016-12-12
  • sockjs前端WebSocket二次封装示例详解

    sockjs前端WebSocket二次封装示例详解

    这篇文章主要为大家介绍了sockjs前端WebSocket二次封装示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • 在微信小程序中渲染HTML内容3种解决方案及分析与问题解决

    在微信小程序中渲染HTML内容3种解决方案及分析与问题解决

    在开发微信小程序时我们会在小程序内加入纯HTML代码,且HTML中包括图片,视频,甚至是事件,微信小程序为我们提供了3种解决方法,但它们的功能与实现方式与最终效果并不理想
    2020-01-01
  • js中ES6继承和ES5继承之间的差别

    js中ES6继承和ES5继承之间的差别

    这篇文章主要介绍了ES6继承和ES5继承,以及两个继承之间的差别,文中运用示例以及代码讲解的非常清晰,感兴趣的小伙伴可以参考一下
    2021-08-08
  • JavaScript中的设计模式 单例模式

    JavaScript中的设计模式 单例模式

    这篇文章主要给大家介绍的是JavaScript中的单例模式,设计模式代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案,需要的朋友可以参考一下
    2021-09-09
  • Proxy Facade设计模式简化系统访问的强大工具原理详解

    Proxy Facade设计模式简化系统访问的强大工具原理详解

    这篇文章主要为大家介绍了 Proxy Facade设计模式简化系统访问的强大工具原理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • JavaScript中5个常用的对象

    JavaScript中5个常用的对象

    JavaScript是一门脚本语言,不同于Python的是,它是一门浏览器脚本语言,而Python则是服务器脚本语言,我们不光要会Python,还要会JavaScript,因为它对做网页方面是有很大作用的。本篇内容小编就来详细解说JavaScript常用的对象,需要的朋友可以参考一下
    2021-10-10
  • TypeScript顺时针打印矩阵实现实例详解

    TypeScript顺时针打印矩阵实现实例详解

    这篇文章主要为大家介绍了TypeScript顺时针打印矩阵实现实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • TypeScript新语法之infer extends示例详解

    TypeScript新语法之infer extends示例详解

    这篇文章主要为大家介绍了TypeScript新语法之infer extends示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08

最新评论