如何使用facebook/immutable-js制作自定义不可变类型? [英] How do I make a custom immutable type using facebook/immutable-js?
问题描述
我正在尝试创建一个简单的不可变的Interval类型.它具有开始和结束属性.有没有一种直接的方法来利用 immutable-js 库来创建您自己的自定义不可变类型?
I am attempting to make a simple immutable Interval type. It has a start and an end property. Is there a straightforward way to utilize the immutable-js library to create your own custom immutable types?
我当前对Immutable.Map和Immutable.List使用包含模式的尝试效果不佳.例如,difference
应该返回一个不可变的Interval列表,但是由于它创建了Interval的新实例,因此它返回的List将不会传递相等性.
My current attempt at using a containment pattern with Immutable.Map and Immutable.List is not working so well. difference
, for example, should return an immutable list of Intervals, but because it creates new instances of Interval, the List it returns will not pass equality.
感觉好像我采用了错误的方法,但是我不确定该怎么做.我可以轻松地用Immutable.Map
表示数据,但我想在其公共接口中包含difference
,而不要包括诸如get和set之类的常规Map
方法.也就是说,我希望它是不可变的,但要具有自己的接口类型.
It feels like I am taking the wrong approach, but I'm not sure how. I could easily represent the data with Immutable.Map
, but I want to include difference
in its public interface, and not include general Map
methods like get and set. i.e. I want it to be immutable, yet be its own type with its own interface.
var Immutable = require('immutable')
function Interval(start, end) {
this.value = Immutable.Map({
start: start,
end: end
})
}
Interval.prototype.start = function () {
return this.value.get('start')
}
Interval.prototype.end = function () {
return this.value.get('end')
}
Interval.prototype.equals = function(interval) {
return this.value.equals(interval.value)
}
Interval.prototype.difference = function (subtrahend) {
var nonoverlapping = subtrahend.start() > this.end() || subtrahend.end() < this.start()
return nonoverlapping ? Immutable.List.of(this) :
Immutable.List.of(
new Interval(this.start(), subtrahend.start()),
new Interval(subtrahend.end(), this.end())
)
.filter(function(interval) {
return interval.end() > interval.start()
})
}
一些测试:
it('should return an empty array for an exact difference', function() {
var interval = new Interval(80, 90)
interval.difference(interval)
.equals(Immutable.List())
.should.be.true
})
it('should return an array with the same Interval for a missed difference', function() {
var interval = new Interval(80, 90)
console.log(interval.difference(new Interval(50, 60)).toJS());
interval.difference(new Interval(50, 60))
.equals(Immutable.List.of([
{ value: Immutable.Map({ start: 80, end: 90 }) }
]))
.should.be.true
})
推荐答案
为什么不使用Record
类型:
var Interval = Immutable.Record({start: 0, end: 1})
这将为您创建记录类型,分别定义默认值0和1的start
和end
属性.
This creates the record type for you, defining start
and end
properties with default values of 0 and 1, respectively.
现在要创建Interval
的实例,只需执行以下操作:
Now to create instances of Interval
, just do:
var newInterval = new Interval() //will have default values above
var newInterval = new Interval({start: 10, end: 30)
请注意,Record
类型的实例只是值类型,因此它们应仅包含数据.当然,您可以定义对此数据值进行运算的函数.
Note that instances of Record
type are just value types, so they should just contain data. You can, of course, define functions that operate on this data value.
var difference = function (interval1, interval2) {
var nonoverlapping = interval2.start > interval1.end || interval2.end < interval1.start
return nonoverlapping ? Immutable.List.of(interval1) :
Immutable.List([
new Interval({start: interval1.start, end: interval2.start}),
new Interval({start: interval2.end, end: interval1.end})
])
.filter(function(interval) {
return interval.end > interval.start
});
}
使用Immutable.is(interval1, interval2)
有关记录类型的更多信息: http://facebook.github. io/immutable-js/docs/#/Record
For more information on the record type: http://facebook.github.io/immutable-js/docs/#/Record
这篇关于如何使用facebook/immutable-js制作自定义不可变类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!