使用getter和setter实现函数链接的方法

Approach to function chaining with getters and setters

本文关键字:链接 方法 函数 实现 getter setter 使用      更新时间:2024-06-20

如果我想使用fluent函数链来支持对象属性的分配。例如:

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

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

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

但是,如果我想能够支持上面的函数链接,但直接赋值,比如:

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

我可以通过添加这样的设置器来添加这种支持:

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返回一个函数,如果使用参数调用它,则该函数设置值;如果不使用参数调用,则返回值。这与API jQuery为.text().html()以及许多其他内容提供的类似,但它为您提供了直接分配给属性的附加选项。我真的不建议这样做,因为能够做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);
    }
}

这样你既可以吃蛋糕也可以吃。