首页 > 解决方案 > rxjs:扫描累加器突变

问题描述

我(错误地)认为扫描操作员每次通过都会返回一个新对象。我最近发现事实并非如此。

我已经从learnrxjs.io分叉了这个例子来演示我在这里的意思。

看一下代码:

const subject = new Rx.Subject();

const example = subject.scan((acc, curr) => {
    console.log('Accumulator', acc);
    return Object.assign({}, acc, curr)
}, {});

//log accumulated values
const subscribe = example.subscribe(val => {
    val.mutating = 'test'
    console.log('Accumulated object:', val)
});

//next values into subject, adding properties to object
subject.next({name: 'Joe'}); 
// {name: 'Joe'}

subject.next({age: 30}); 
// {name: 'Joe', age: 30}

subject.next({favoriteLanguage: 'JavaScript'}); 
// {name: 'Joe', age: 30, favoriteLanguage: 'JavaScript'}

我正在改变val传递的流subscription并注销累加器函数accumulator中的值。scan

查看控制台,它显示累加器包含mutating:"test"在第一次和后续传递之后:

在此处输入图像描述

除非我弄错了,否则这表明我可以在订阅线和订阅线的任何位置改变流对象。我想这并不让我感到惊讶,因为它是一个对象引用。但是,我认为scan运算符总是会返回一个新对象,以防止其内部累加器发生变异......

我首先想到的是映射一个像这样的新对象:

scan((acc, curr) => Object.assign({}, acc, curr), {}),
map(data=>Object.assign({}, data))

但这对我来说似乎很奇怪。

我展示的行为是预期的还是我不理解这一切是如何运作的?如何防止累加器发生变异?

谢谢

标签: rxjsrxjs6

解决方案


是的,它是一个对象引用->acc您正在更改。您可以像下面这样冻结对象以阻止它发生变异。

 return Object.freeze(Object.assign({},acc, curr));

推荐阅读