JavaScript setter/getter的使用方法

3

所以我得到了我的 Cube 类

class Cube{
    constructor(txt){
        this._text = txt;
    }
    get text(){
        return this._text;
    }
    set text(txt){
        this._text = txt;
    }
}

我可以实现这样的东西。
let temp = new Cube('hello');

目前,我还不明白为什么要使用setter和getter,因为我两者都可以做:

temp.text = 'bye';
console.log(temp.text);//shows bye
console.log(temp._text);//shows bye
temp._text = 'hello again';
console.log(temp.text);//shows hello again
console.log(temp._text);//shows hello again

所以我假设我只想在需要执行以下操作时使用设置器:

set text(txt){
    this._text += txt;
}

使用设置器和获取器的其他原因是什么?


4
想想你可以在setter或getter函数中做任何想做的事情,它们只是函数。 - Pointy
1个回答

6

目前我还不明白使用setter和getter的意义,因为我可以通过使用text_text两种方式来实现。

这只是因为你将值存储在了实例属性中。其实你并不一定要这样做,你可以将它存储在其他地方:

const Cube = function() {
  const privateData = new WeakMap();
  return class Cube {
    constructor(txt){
      privateData.set(this, {text: txt});
    }
    get text(){
      return privateData.get(this).text;
    }
    set text(txt){
      privateData.get(this).text = txt;
    }
  };
};

let temp = new Cube('hello');
temp.text = 'bye';
console.log(temp.text);  // shows bye
console.log(temp._text); // shows undefined

或者只是让它在班级之外更难使用(但不是不可能):

const Cube = function() {
  const textProp = Symbol();
  return class Cube {
    constructor(txt){
        this[textProp] = txt;
    }
    get text(){
        return this[textProp];
    }
    set text(txt){
        this[textProp] = txt;
    }
  };
};

let temp = new Cube('hello');
temp.text = 'bye';
console.log(temp.text);  // shows bye
console.log(temp._text); // shows undefined

还要注意的是,由于getset只是函数,因此你可以在其中执行任何操作。例如,也许set text会删除任何前导和尾随空格。也许根本没有set text,只有一个getter。也许设置text会更新其他属性。也许它记录更改,以便您可以提供该更改的“撤消”。也许它为调试版本记录更改日志。
选择无穷无尽。重点是通过为您提供一种连接到属性get/set操作的方式,您可以对其执行任何操作。(当然,您既可以使用也可以滥用... :-))
在评论中,您问道:

所以在我的情况下(第一个代码片段),基本上不需要get/set(因为我不想修改输入和输出)?

如果您只想要一个普通、无聊的属性(这通常是我们大部分时间想要的),则不需要getter/setter,只需使用普通属性即可:
class Cube {
    constructor(txt) {
        this.text = txt;
    }
}

而且很棒的是,如果您后来意识到需要一个getter/setter,您可以更改它,使用编写的代码仍然有效。 :-)


当然,在现实生活中,许多人只是为类中每个属性创建像问题中的那样的设置器和获取器(嘿,即使IDE也有自动化功能来完成它!),因为你知道,将它们公开会破坏封装;-) - Álvaro González
那么在我的情况下(第一个代码片段),基本上不需要使用get/set(因为我不想修改我的输入和输出)? - user3006119
1
如果您只需要一个普通、单调的属性(这通常是我们大部分时间所需的),就不需要使用 getter/setter,只需使用普通属性即可。更妙的是,如果您后来意识到需要 getter/setter,您可以更改它,并且使用“Cube”编写的代码仍然有效。 :-) - T.J. Crowder
@ÁlvaroGonzález 但是正如你所看到的,我仍然可以访问这些属性,这并没有实现封装。 - user3006119
@user3006119:他是在讽刺。 :-) - T.J. Crowder
1
是的,我当时是在讽刺,但这是需要考虑的事情,因为我经常在实际代码中看到它。换句话说:并不是你在现实中看到的每个模式都必须有意义。 - Álvaro González

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接