ECMAscript 6:观察 class 属性的变化

ECMAscript 6: watch changes to class properties

假设我有一个 class 定义如下:

class MyClass {

    constructor (a) {
        this.a = a;     
    }

    _onPropertyChanged() {
        // do something
    }
}

每当 MyClass 实例的 属性 "a" 发生变化时,我想触发该实例的 _onPropertyChanged 方法。 使用 ECMAscript 6 实现此目的的最佳(最高性能)方法是什么?

没有'best'方法,实际方法总是取决于最终目标。

在其简单(且性能足够)的形式中,它是:

class MyClass {

    constructor (a) {
      this.a = a;     
    }

    get a() {
      return this._a;
    }

    set a(val) {
      this._a = val;
      this._onPropertyChanged('a', val);
    }

    _onPropertyChanged(propName, val) {
        // do something
    }
}

这是一个简单的示例,说明您可以针对这种情况和单个 属性 执行哪些操作。

class MyClass {

constructor (a) {
    this._a = a;
}

set a(value) {
    let hasChanged = (this._a !== value);
    this._a = value;
    //Assumes value is primitive. Customize for objects
    if(hasChanged) this._onPropertyChanged();

}

_onPropertyChanged() {
    // do something
}
}

最简单的事情就是像所说的那样为属性定义一个setter和一个getter。但是,如果您已经定义了 setter.

,它将不起作用

另一种方法是非标准的 Object.prototype.watch,它只能在 Gecko 中原生使用。如果你想将它的支持带到大多数其他浏览器,你可以使用一个小而强大的 Andrea Giammarchi's library.

最好的方法是重新定义 filed/property,但在这种情况下你会遇到一些陷阱,比如 'find owner of this prop'。您可以使用 this 解决方案进行完全安全的 属性 重新定义。

主要思想是重新定义 属性 如果存在:

 Object.defineProperty(target, name, {
     get() { return get(ownPropertyDescriptor.get.call(target)); },
     set(val) {
         let _val = set.call(this, val);
         if (_val != undefined)
            ownPropertyDescriptor.set.call(target, _val);
         },
     configurable: true
 });

或根据 symbol 类型创建新的 属性:

var indexer = Symbol(name);
target[indexer] = target[name];
Object.defineProperty(target, name, {
  get() {
         var val = target[indexer];
         var _val = get(val);
           return _val;
     },
  set(val) {
         let _val = set.call(this, val);
         arget[indexer] = set(_val);
     },
  configurable: true
});

Full method is part of complex solution for property-redefining.