不可变的js:使函数更多..功能性

时间:2016-01-25 11:45:50

标签: javascript ecmascript-6 immutable.js

我有一个适用于Immutable.js条记录的减速机功能,Calendar

const Calendar = new Record({
    'events': new List(), // list of Events
});

这是Event s:

的列表
const Event = new Record({
    'start': null,
    'end': null,
    'title': null,
});

我想将Javascript对象中的新事件添加到此列表并返回新的Calendar记录,但前提是这些对象不在列表中:

(state = new Calendar)=> {

    const receivedEvent = new Event({
        start: <a date>,
        end: <another date>,
        title: <a string>,
    });

    let newState;

    if (state.get('events').contains(receivedEvent)){
        newState = state;
    } else {
        newState = state
            .updateIn(['events'], (events)=> events.push(receivedEvent));
    }

    return newState;  
}

这是我现在凌晨4点才能做的最好的事情,但这似乎是一种糟糕的做法。

有没有办法更好地利用Immutable提供的功能范例来完成同样的任务?

2 个答案:

答案 0 :(得分:2)

如果您正在处理会员资格很重要的集合,那么您可能希望使用Set而不是列表。

集合只是一组唯一值。

const Calendar = new Record({
  'events': new Set(), // set of Events
});

然后,您可以将事件添加到集合中,而不必担心会出现重复值。数据结构的实现使您无需检查它是否已包含该值。

(state = new Calendar) =>
  state.updateIn(['events'], calendar => calendar.add(new Event({
    start: <a date>,
    end: <another date>,
    title: <a string>,
  }));

当您表示日历时,添加事件的顺序可能并不重要,因为您可以使用事件日期本身作为列表进行排序,否则,您可以使用OrderedSet来保留日历排序

答案 1 :(得分:1)

您遇到的问题是List.contains会使用Event将每个receivedEvent===进行比较。

即使receivedEvent可能与您状态中已存储的属性共享相同的属性,但它们不是相同的对象。

示例:

const x = { a: 1, b: 2 };
const y = { a: 1, b: 2 };
const z = x;

x === y; // -> false
x === x; // -> true
x === z; // -> true

因此,您需要将receivedEvent的每个属性与您要比较的每个实例进行比较。谢天谢地,有handy Immutable.is method,您可以这样使用:

if (state.get('events').some(event => Immutable.is(receivedEvent, event))) {
    // already exists in events
} else {
    // doesn't already exist in events
}