Immutable.js getters用于以对象文字表示法调用函数

时间:2017-02-14 22:26:53

标签: javascript immutable.js enumerable

我试图将函数传递给Map,就像使用对象文字表示法一样。有没有任何本机可以调用函数,就像你在枚举上使用getter方法一样?

var person = {
  firstName: 'John',
  lastName: 'Smith',
  format: function() {
    return this.lastName + ', ' + this.firstName;
  }
};

person.format(); // 'Smith, John'

var personMap = new Immutable.Map(person);

personMap.get('format'); // function() {return ... // doesn't work

1 个答案:

答案 0 :(得分:1)

我对Immutable.js并不熟悉,但你可以在进入集合之前将函数绑定到正确的this

最简单的情况:

person.format.bind (person);
// create immutable here

更一般地说,如果我可以假设集合是您打算引用该对象的唯一方式,并且继承的方法不是问题:

function objectAsCollection (object) {
    var key;
    for (key of Object.keys (object)) {
        if (typeof object [key] == "function") {
            object [key] = object [key].bind (object);
       }
    }
    return new Immutable.Map (object);
}

这确实会修改原始对象,但调用person.format ()的方式不受影响,而mapYouMade.get ("format")()this指向person。根据您的其余代码,可能会出现一些问题:

  • 如果person成为对象或类的原型,则该函数将始终表现为this.format仍然引用原型而不是派生对象。
  • 如果修改了person.whateverProperty,则更改不会反映在不可变映射中,但theMap.get ("format")()将使用新值,因为它绑定到原始对象,而不是映射中的条目,这意味着不可变的方法是非常可变的。

听起来你想要的并不是一个不可变的地图,而是一个不可变的对象;毕竟,集合用于同类值类型,方法属于它们所属的对象。我在这种情况下的建议是忘记Immutable.js并使用:

Object.freeze (person);

这使得对象本身不可变,没有集合固有的危险。如果由于某种原因只是必须有一个集合,则必须扩展集合类和/或使用代理来获取format以从其包含集合中获取其他条目,以便person可以独立变异。请注释是否是这种情况,我可以告诉你如何做,但我不熟悉Immutable.js类,代理是一个复杂的野兽。