代码之家  ›  专栏  ›  技术社区  ›  diplosaurus

简单的检索和分配getter和setter在javascript中有用吗?

  •  1
  • diplosaurus  · 技术社区  · 7 年前

    对于javascript中的每个属性重复此模式是否有意义?

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

    我理解,如果您在方法中做额外的工作,getter/setter可能很有用,但是在这里重新创建基本功能似乎是不必要的重复。如果我实例化,我仍然可以操纵backing属性( ._myProp )直接地,所以我觉得我可以很容易地把这些排除在外,以更典型的、特别的方式执行我的任务和访问。

    我想您可能会争辩说,用这种方式定义接口(使用带下划线前缀的属性名)会向用户发出信号,表明它无意操纵属性,但这似乎是可能存在几十个属性的脆弱原因。

    4 回复  |  直到 7 年前
        1
  •  4
  •   sripberger    7 年前

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

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

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

        2
  •  1
  •   apsillers    7 年前

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

    唯一的优点是,如果您想在将来引入更复杂的访问器行为,那么修改代码就容易了。如果您放弃了添加访问器行为的需要,那么可以使用此模式来节省将来的时间。

        3
  •  0
  •   Estus Flask    7 年前

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

    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;
      }
    }
    
        4
  •  -1
  •   mpm    7 年前

    如果我实例化,我仍然可以操纵backing属性 (u myprop)直接,

    如果你正在寻找的是私有国家,你仍然可以使用弱地图。

    (function(scope) {
      "use strict";
      const prop = new WeakMap();
    
      scope.Foo = class {
        constructor() {
          prop.set(this, {});
          Object.seal(this);
        }
        get bar() {
          return prop.get(this)._bar;
        }
        set bar(value) {
          return prop.get(this)._bar = value;
        }
      }
    
    
    }(this))
    
    const f = new Foo;
    
    f.bar = "bar";
    f._bar = "_bar";
    console.log(f.bar);
    console.log(f._bar);

    get和setter在实现MVC时也很有用,您可以在属性更改时触发事件。

    (function(scope) {
      "use strict";
      const prop = new WeakMap();
    
      scope.Foo = class {
        constructor() {
          prop.set(this, {});
          prop.get(this)._target = new EventTarget
          Object.seal(this);
        }
        get bar() {
          return prop.get(this)._bar;
        }
        set bar(value) {
          prop.get(this)._bar = value;
          prop.get(this)._target.dispatchEvent(new CustomEvent('change', {
            detail: value
          }));
        }
        addEventListener(event, listener) {
          prop.get(this)._target.addEventListener(event, listener)
        }
      }
    
    
    }(this))
    
    const f = new Foo;
    f.addEventListener('change', function(event) {
      console.log("changed!", event.detail);
    });
    f.bar = "bar";
    推荐文章