用陷阱覆盖ES6类行为

时间:2018-08-06 22:43:58

标签: node.js ecmascript-6

我最近了解了javascript中的Proxy对象,以及如何使用代理对象将Object.defineProperty挂接到自定义行为(如果我不太清楚,请参见this answer) )。

我想对整个类做同样的事情,以便可以实现类似于C#的INotifyPropertyChanged接口。本质上,该类将是EventEmitter,它在更改属性时会发出数据。

class SyncedObject extends EventEmitter {
    constructor() {
        this.ValueA = 1;
        this.ValueB = 2;
    }

    // Emit this when a property is changed
    emitPropertyChanged( eventArgs ) {
        // eventArgs.propertyName
        // eventArgs.oldValue
        // eventArgs.newValue

        this.emit( 'propertyChanged', eventArgs );
    }
}

这是我在ES6课程中可以做的事情吗?我知道Proxy有一个get()set()陷阱可以实现这种目的,但是我不确定如何编写自动包装在{{ 1}}。

1 个答案:

答案 0 :(得分:2)

经过一番修补,我已经或多或少地实现了我希望达到的目标

const EventEmitter = require( 'events' );

class SyncedObject extends EventEmitter { 
  constructor( obj ) {
    super();
    this._object = obj;

    return new Proxy( this, {
      set: ( object, key, value, proxy ) => {
        if( this._object[key] === value )
          return false;

        this._object[key] = value;
        if( key[0] === '_') {
            var eventArgs = {
              propertyName: key,
              oldValue: object[key],
              newValue: value
            };
            this.emit( 'propertyChanged', eventArgs );
        }

        return true;
      },
      get: ( object, key ) => {
        return this._object[key] || object[key];
      }
    });
  }

  silentUpdate( data ) {
    for(var i = 0, keys = Object.keys(data); i < keys.length; i++)
      this._object[keys[i]] = data[keys[i]];
  }

}

不是最可靠的解决方案(EventEmitter属性引发事件),但是对于我所需要的,它可能会做到。如果有人有改进建议,请发表。我暂时不提这个问题。