用getter和setter进行函数链接的方法

时间:2015-02-27 19:58:18

标签: javascript ecmascript-6

如果我想使用流畅的函数链来支持对象属性的赋值。例如:

foo.width(500).height(250).margin({left:5,right:10});

我显然可以创建一个函数定义,如:

margin(value) {
    this.config.margin = value;
    return this;
}

但是,如果我希望能够支持上述功能链接,但直接分配如下:

foo.margin = {left:5,right:10};

我可以通过添加如下的setter来添加此支持:

set margin(value) {
    this.config.margin = value;
}

但你不能拥有一个同名的setter和一个函数,显然setter只能用于文字赋值操作,而函数定义只适用于流畅的API方法。

有没有办法在语法上优雅地使用JS ES6?


我已经包含了一个小提琴,演示了流利和文字作业运算符的工作示例。唯一的问题?我不得不求助于使用不同的命名签名来增加API表面...如果可能的话我想避免这种情况。

http://www.es6fiddle.com/i6o0jscx/

2 个答案:

答案 0 :(得分:2)

如果您愿意使用额外的两个字符检索属性值,那么您可以这样做:

export class Foo {
  constructor() {
    this.config = {
      width:500,
      height: 400
    };
  }

  get width() {
    return function(value) {
      if (arguments.length) {
        this.config.width = value;
        return this;
      }
      return this.config.width;
    };
  }
  set width(value) {
    this.config.width = value;
  }
}

let foo = new Foo();
console.log(foo.width());
foo.width = 600;
console.log(foo.width());
console.log(foo.width(250).width());

基本上,getter返回一个函数,该函数在使用参数调用时设置值,或者在没有参数的情况下调用它时返回值。这与API jQuery为.text().html()以及许多其他内容提供的类似,但它为您提供了直接分配给属性的附加选项。我不会真的推荐这个,因为能够foo.width = 5;而不是var w = foo.width;会让人感到困惑,但是我无法找到一个完全实现你的目标的好方法。 #39;重新尝试。

http://www.es6fiddle.com/i6o14n4b/

答案 1 :(得分:1)

你可以同时拥有两者。您只需坚持命名约定:

class Thing {
  constructor() {
    this._property = 0;
  }

  get property() {
    return this._property;
  }

  set property(property) {
    this._property = property;
  }

  setProperty(property) {
    this.property = property;
    return this;
  }
}

这样你就可以吃蛋糕了。