Javascript 在array.prototype.map(RxJS管道中)中返回副本或操作原始对象之间的差异

Javascript 在array.prototype.map(RxJS管道中)中返回副本或操作原始对象之间的差异,javascript,angular,rxjs,rxjs-pipeable-operators,Javascript,Angular,Rxjs,Rxjs Pipeable Operators,我正在开发Angular 9,RxJS 6应用程序,我有一个关于管道主题值和在管道中进行单位转换的不同结果的问题 请看一看。在backend.service.ts文件中,创建了一个observable,它执行一些单位转换,并返回提交给_商品主题的所有内容。如果您查看convertCommodityUnits函数,请注意,我注释了工作示例,而使用了最初解决它的方法 我的问题:当您使用屏幕上的“取消订阅”按钮并再次订阅时,当使用仅覆盖对象而不进行复制的转换解决方案时,HTML中的值会被转换多次,因此

我正在开发Angular 9,RxJS 6应用程序,我有一个关于管道主题值和在管道中进行单位转换的不同结果的问题

请看一看。在backend.service.ts文件中,创建了一个observable,它执行一些单位转换,并返回提交给_商品主题的所有内容。如果您查看convertCommodityUnits函数,请注意,我注释了工作示例,而使用了最初解决它的方法

我的问题:当您使用屏幕上的“取消订阅”按钮并再次订阅时,当使用仅覆盖对象而不进行复制的转换解决方案时,HTML中的值会被转换多次,因此管道不会使用主题提供的原始数据。如果使用其他代码,则在convertCommodityUnits中创建商品对象的克隆,其工作原理与预期相同

现在,我不明白为什么转换数据的两种方式表现得如此不同。我得到了一个直接操作数据的方法,因为js是这样做的,一个返回一个新对象。但是传递给convertCommodityUnits函数的对象是由array.prototype.map函数创建的,所以它不应该覆盖任何内容,对吗?我希望RxJS使用发送到主体的原始、最后的数据传递到管道/贴图操作符,但在示例中似乎不是这样,对吗

如何/为什么在此处多次转换值

这或多或少是关于这个的后续问题:,所以它是相同的设置。

当您使用map时,您得到了一个新的数组引用。但是,在新生成的数组浅拷贝中没有新的对象,因此您正在改变元素中的数据

在解构解决方案中,因为数组中的每个对象中只有基元类型,所以每次调用转换方法时,都会向数组生成全新的元素。这一点很重要:不仅是新数组,而且数组中的新元素=>您已经执行了数组的深度复制。因此,您不会在每个订阅中连续累积值

这并不意味着像您在所提供的stackblitz演示中使用的1级分解解决方案在所有情况下都能工作。我在那里看到过很多这样的错误,特别是在redux模式框架中,它需要您不改变存储的数据,如ngrx、ngxs等。如果您的数组中有复杂的对象,那么1级的分解将不会影响数组中每个元素中的所有嵌入对象。我认为用例子来描述这种行为更容易:

常量obj1={a:1}; 常量数组=[{b:2,obj:obj1}]; //在下面代码中的每个newArray赋值之后, //console.lognewArray==数组向控制台打印false 让newArray=[…array]; console.logarray[0]==newArray[0];//符合事实的 newArray=array.mapitem=>item; console.logarray[0]==newArray[0];//符合事实的 newArray=array.mapitem=>{…项}; console.logarray[0]==newArray[0];//错误的 console.logarray[0]。obj==newArray[0]。obj;//符合事实的 newArray=array.mapitem=>{ 项目 obj:{…item.obj} }; console.logarray[0]==newArray[0];//错误的 console.logarray[0]。obj==newArray[0]。obj;//错误的
如果我没有很好地解释我的问题,请随时告诉我,以便我可以澄清我的意思。如果你愿意,请在问题本身中发布与问题相关的所有代码-不要隐藏在链接后面。你不应该告诉那些想帮忙的潜在帮手,他们必须在异地工作,只是为了了解你在做什么。如果链接中断,这个问题可能对未来的读者毫无用处。请将您的代码编辑到a中的问题中,否则问题可能会关闭,谢谢。我想我明白了,谢谢!这绝对是有道理的,尽管我有点担心RxJS管道中的情况也是如此。我多次检查,主题的数据没有通过直接订阅来修改,我想我可以确定RxJS管道在调用管道时总是使用主题的最新发出值,而不是以前修改过的值。你所说的意思是,对象是通过数组中存储的引用修改的,但是主体没有注意到这个更改,对吧?没错。主体正在发射一个包含旧对象的新数组。这就是对内存中对象的引用。Array.prototype.map仅确保对同一数组有一个新引用。它分配一个新内存地址,其中包含另一个内存地址作为其值:数组第一个元素的内存地址。每个元素的新内容由您决定。