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

Approach to function chaining with getters and setters

如果我想支持使用流畅的函数链接来分配对象属性。例如,类似于:

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 中以语法优雅的方式兼顾两者?


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

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

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

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 returns 一个函数,如果调用时带参数,则设置值;如果调用时不带参数,则 returns 设置值。这类似于 API jQuery 为 .text().html() 提供的许多其他内容,但它为您提供了直接分配给 [=29 的附加选项=].我不会真的推荐这个,因为能够做到 foo.width = 5; 而不是 var w = foo.width; 令人困惑,但我看不到完全实现你想要做的事情的好方法。

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

你可以两者兼得。您只需要遵守命名约定即可:

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

    get property() {
        return this._property;
    }

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

    set property(property) {
        this.setProperty(property);
    }
}

这样你就可以吃到蛋糕了