使用getter&setter和公共属性之间的区别

use*_*902 0 javascript

我是JS的新手,正在学习JS中的抽象以及getter和setter的使用。因此,据我所知,可以使用object.defineProperty来实现getter和setter,但是,伙计们,为什么要通过getter和setter而不是公共财产来访问私有财产呢?因为,使用getter可以读取私有财产,而使用setter可以将新值设置为私有财产。如果我们使用公共财产也可以读取公共财产的价值并为其设置新的价值,这是不一样的。当我们可以使用公共属性同时实现getter和setter时,我只是无法理解为什么要使用getter和setter。希望你明白我的意思。

Cer*_*nce 5

通常,在属性访问时,除了简单地设置/检索数据之外,类还需要执行某些操作时,getter / setter很有用。例如:

class MyClass {
  constructor() {
    this.setHistory = [];
  }
  set item(newVal) {
    this.setHistory.push(newVal);
    this._item = newVal;
  }
  get item() {
    return this._item;
  }
}

const f = new MyClass();
f.item = 'foo';
f.item = 'bar';
console.log(f.setHistory);
Run Code Online (Sandbox Code Playgroud)

在上面,可以使用设置功能存储以前设置了哪些项目的“历史记录”。如果没有setter函数,则只有一个公共item属性,该类无法保存历史记录。

如果getter / setter所要做的只是设置或检索值,那么您说对了,它几乎没有用,例如:

class MyClass {
  set item(newVal) {
    this._item = newVal;
  }
  get item() {
    return this._item;
  }
}

const f = new MyClass();
f.item = 'foo';
f.item = 'bar';
console.log(f.item);
Run Code Online (Sandbox Code Playgroud)

在这里,setter和getter根本没有做任何有用的事情,因此您可以删除它们。通常,当您要执行除存储/检索值之外的其他操作时,请使用setter / getter 。

setter和getter还可用于隐藏对消费者不重要的实现细节。(例如,分配给.innerHTML非常相似于调用一个setter)。

它们在调试时也很有用,例如在更改对象时记录日志。

一个警告:上面的第一个代码片段实际上并没有使用“私有”属性,它只是使用_-prefix约定来指示该属性不应在外部使用。对于无法从外部访问的真实私有属性,应定义WeakMap并使用IIFE创建类:

// with this class,
// neither item nor history can be accessed without going through the getters
const MyClass = (() => {
  const privateDatas = new WeakMap();
  return class MyClass {
    constructor() {
      privateDatas.set(this, { setHistories: [] });
    }
    set item(newVal) {
      const privates = privateDatas.get(this);
      privates.setHistories.push(newVal);
      privates.item = newVal;
    }
    get item() {
      return privateDatas.get(this).item;
    }
    getSetHistory() {
      return privateDatas.get(this).setHistories;
      // if you want to make sure the internal array doesn't get mutated outside,
      // return a copy: .setHistories.slice()
    }
  }
})();

const f = new MyClass();
f.item = 'foo';
f.item = 'bar';
console.log(f.getSetHistory());
Run Code Online (Sandbox Code Playgroud)