简单的检索和赋值getter和setter在JavaScript中有用吗?

简单的检索和赋值getter和setter在JavaScript中有用吗?,javascript,class,ecmascript-6,getter-setter,Javascript,Class,Ecmascript 6,Getter Setter,对JavaScript中的每个属性重复此模式有意义吗 class Thing { get myProp() { return this._myProp; } set myProp(value) { this._myProp = value; } } 我理解,如果您在方法中做额外的工作,getter/setter可能会很有用,但是在这里重新创建基本功能似乎是不必要的重复。如果我实例化,我仍然可以直接操作backing属性(。\u myProp),因此我觉得我可以同

对JavaScript中的每个属性重复此模式有意义吗

class Thing {
  get myProp() {
    return this._myProp;
  }
  set myProp(value) {
    this._myProp = value;
  }
}
我理解,如果您在方法中做额外的工作,getter/setter可能会很有用,但是在这里重新创建基本功能似乎是不必要的重复。如果我实例化,我仍然可以直接操作backing属性(
。\u myProp
),因此我觉得我可以同样轻松地忽略这些属性,以更典型的临时方式执行分配和访问


我想您可能会争辩说,以这种方式定义接口(带有下划线前缀的属性名)向用户发出信号,表明它不是为了操纵属性,但这似乎是一个不可靠的理由,因为可能有几十个这样的接口。

以您描述的方式使用访问器属性(设置并检索“背景”数据属性)实际上在语义上与直接使用数据属性相同。有一些区别:accessor属性将存在于实例的原型上,而不是直接存在于实例上(尽管实例将具有“background”数据属性),但这不会真正影响任何东西,除非您对类实例进行高级内省


如果您希望在将来引入更复杂的访问器行为,那么唯一的优点是易于修改代码。如果您认为需要添加访问器行为,请使用此模式以节省将来的时间。

按照您描述的方式使用访问器属性(设置并检索“后台”数据属性)在语义上实际上与直接使用数据属性完全相同。有一些区别:accessor属性将存在于实例的原型上,而不是直接存在于实例上(尽管实例将具有“background”数据属性),但这不会真正影响任何东西,除非您对类实例进行高级内省


如果您希望在将来引入更复杂的访问器行为,那么唯一的优点是易于修改代码。如果您认为需要添加访问者行为,请使用此模式以节省将来的时间。

属性访问者可用于提供副作用或更改原始行为:

class Thing {
  get myProp() {
    console.log('myProp was read');
    return this._myProp;
  }
  set myProp(value) {
    if (!value)
      throw new Error('myProp cannot be falsy');
    this._myProp = value;
  }
}
myProp
getter/setter纯抽象没有意义:

class Thing {
  get myProp() {
    return this._myProp;
  }
  set myProp(value) {
    this._myProp = value;
  }
}

属性访问器可用于提供副作用或更改原始行为:

class Thing {
  get myProp() {
    console.log('myProp was read');
    return this._myProp;
  }
  set myProp(value) {
    if (!value)
      throw new Error('myProp cannot be falsy');
    this._myProp = value;
  }
}
myProp
getter/setter纯抽象没有意义:

class Thing {
  get myProp() {
    return this._myProp;
  }
  set myProp(value) {
    this._myProp = value;
  }
}

在编译语言中,人们经常这样做。这是因为在这些语言中,分配给字段和调用setter可能与程序员相同,但它们编译为两种完全不同的操作

例如,如果我想为在C#类中设置字段添加一个副作用,而该字段是直接设置的,而不是通过setter设置的?将其更改为setter将导致一些问题。我不必重写任何消费代码,但我必须重新编译所有代码。当然,如果您的公共发布是编译的,这将是一个巨大的问题


不过,JavaScript不需要考虑这些因素,所以过早地将所有内容都变成getter/setter有点愚蠢。如果你看到有人这样做,你很可能是在和一个从另一种语言学习约定并将其转化为JavaScript的人打交道,而没有考虑太多原因。

在编译语言中,人们这样做是很常见的。这是因为在这些语言中,分配给字段和调用setter可能与程序员相同,但它们编译为两种完全不同的操作

例如,如果我想为在C#类中设置字段添加一个副作用,而该字段是直接设置的,而不是通过setter设置的?将其更改为setter将导致一些问题。我不必重写任何消费代码,但我必须重新编译所有代码。当然,如果您的公共发布是编译的,这将是一个巨大的问题

不过,JavaScript不需要考虑这些因素,所以过早地将所有内容都变成getter/setter有点愚蠢。如果你看到有人这样做,你很可能是在和一个从另一种语言学习了这个约定并将其转化为JavaScript的人打交道,而没有考虑太多原因

如果我实例化,我仍然可以操作backing属性 (._myProp)直接

如果你要寻找的是私人州,你仍然可以使用弱映射

(功能(范围){
“严格使用”;
const prop=new WeakMap();
scope.Foo=class{
构造函数(){
prop.set(这个,{});
对象.印章(本);
}
get bar(){
返回道具。获取(此)。\u条;
}
设置栏(值){
返回prop.get(此)。\u bar=值;
}
}
}(本节)
常数f=新的Foo;
f、 bar=“bar”;
f、 _-bar=“_-bar”;
控制台日志(f.bar);
控制台日志(f.\U条)
如果我实例化,我仍然可以操作backing属性
(._myProp)直接

如果你要寻找的是私人州,你仍然可以使用弱映射

(功能(范围){
“严格使用”;
const prop=new WeakMap();
scope.Foo=class{
构造函数(){
prop.set(这个,{});
对象.印章(本);
}
get bar(){
返回道具。获取(此)。\u条;
}
设置栏(值){
返回prop.get(此)。\u bar=值;
}
}
}(本节)
常数f=新的Foo;
f、 bar=“bar”;
f、 _-bar=“_-bar”;
控制台日志(f.bar);

控制台日志(f.\U条)它有助于控制对该属性的访问。你是否需要它取决于你是否需要,但如果你需要,你希望早点得到它。如果您使用的是getter和setter,那么您可以轻松地做更多的事情——例如对更改做出反应(可观察)。通过不使用setter,可以使属性为只读。你可以有一个完全由计算机计算的“属性”——比如说,
g