You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在RxJS中扩展map运算符?实现带对象克隆的自定义运算符

自定义RxJS运算符mapToVM实现结果深克隆

当然可以通过包装map运算符来实现你的需求,只需要在执行传入的投影函数后,对返回结果进行JSON.parse(JSON.stringify())深克隆即可。这样订阅者拿到的始终是原始对象的副本,不会影响store中的源数据。

修改后的完整代码如下:

import { map, Observable, OperatorFunction, Subject } from "rxjs";

console.clear();

const store = new Subject<{ company: { id: number } }>();

// 对比:原生map返回原对象引用,修改会影响store
store.pipe(map((s) => s.company)).subscribe((company) => {
  console.log("原生map返回的对象:", company);
  company.id = 2;
  console.log("修改后store内的对象:", store.value); // 输出 { company: { id: 2 } }
});

function mapToVM<T, R>(
  project: (value: T, index: number) => R
): OperatorFunction<T, R> {
  return map((value, index) => {
    // 先执行用户传入的投影逻辑
    const result = project(value, index);
    // 对对象类型进行深克隆,原始值直接返回
    if (typeof result !== "object" || result === null) {
      return result;
    }
    return JSON.parse(JSON.stringify(result));
  });
}

// 使用自定义mapToVM,返回克隆后的对象,修改不影响store
store.pipe(mapToVM((s) => s.company)).subscribe((company) => {
  console.log("mapToVM返回的克隆对象:", company);
  company.id = 3;
  console.log("修改后store内的对象:", store.value); // 仍然输出 { company: { id: 2 } }
});

store.next({ company: { id: 1 } });

关键说明:

  • 在mapToVM内部,我们通过map运算符包装了用户的投影函数,先得到投影结果,再对结果做深克隆处理。
  • 增加了对非对象类型(如字符串、数字、null等)的判断,避免无意义的克隆操作,提升性能。
  • JSON.parse(JSON.stringify())是一种简单的深克隆方式,但注意它无法处理函数、Symbol、循环引用等特殊类型,如果你的场景包含这些情况,需要替换为更健壮的深克隆方法(比如lodash的cloneDeep)。

内容的提问来源于stack exchange,提问作者Jon Sud

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 13:25:25