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

Javascript 使用getter和setter进行函数链接的方法,javascript,ecmascript-6,Javascript,Ecmascript 6,如果我想支持使用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}; 我可以通过添加如下sett

如果我想支持使用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};
我可以通过添加如下setter来添加此支持:

set margin(value) {
    this.config.margin = value;
}
但是不能有一个setter和一个同名的函数,显然setter只适用于文本赋值操作,函数定义只适用于fluent-API方法

有没有一种方法可以让JSES6在语法上优雅地兼顾这两个方面


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


如果您愿意使用额外的两个字符来检索属性值,则可以执行以下操作:

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,但我看不到一个好的方法来完全实现您试图做的事情


两者都可以。您只需遵守命名约定:

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

    get property() {
        return this._property;
    }

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

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

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

问题是,为什么要添加与函数同名的属性?我猜这是不可能的,您应该只更改
foo.config.margin='something'
instead@adeneo我不太明白。我认为这在其他语言中是一种相当普遍的做法。您希望确保只能通过setter设置私有/受保护的属性,并且希望访问该属性的人同时具有fluent和literal赋值运算符。@ken No,在其他语言中,有时具有类似于属性的行为,有时具有类似于方法的行为并不是常见的做法。大多数时候都是这样或那样。这就是你在这里试图实现的,这就是你遇到麻烦的原因。^他说的,我不太熟悉ES6,但通常javascript中没有“private”,你创建的函数都是基于传入的参数设置和获取值的,比如
foo.width(400)
设置值
config.width
,和
var w=foo.width()
返回值或类似值。无论你有多喜欢,你都不能同时拥有一个既是原语又是函数的属性。@JLRishe在PHP中(我相信是Ruby),尽管这很容易做到,而且在我看来是经常做到的。好的,谢谢@JLRishe。这是一个“很好的拥有”,但如果不可能,我可以没有它。我真的很喜欢Fluent接口方法,当你有大量属性要设置时,但当有一次性属性时,我更喜欢文字赋值。@ken嗯,就像我说的,这两种东西都有可能,但折衷是,您必须使用
()
来检索值。但是如果你偏爱流利的方法,我建议你坚持。它更灵活,文字赋值实际上没有任何主要的好处。这不仅仅涉及两个额外的字符,因为它需要另一个超出方法职责范围的条件块。请看我的答案,寻找一种更简洁的方法。是的,我以前使用过这种方法,我认为命名约定非常明确。不过,在大多数情况下,我还是决定走一条或另一条路,但不是两条都走。不过谢谢你的建议。。。这是一个很好的方法。OP要求能够使用与setter方法和setter属性相同的属性名。你的例子根本没有提供这一点。显然,这种方法是有效的——它非常琐碎,但我的回答非常接近OP要求的内容。@JLRishe你是对的,我的观点是正确的。