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

用陷阱重写ES6类行为

  •  1
  • w0f  · 技术社区  · 6 年前

    我最近了解到 Proxy javascript中的对象,以及如何使用代理对象钩住 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班能做的吗?我理解 代理 有一个 get() set() 可以实现这种功能的陷阱,但我不确定如何编写一个自动包装在 代理 .

    1 回复  |  直到 6 年前
        1
  •  2
  •   w0f    6 年前

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

    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属性引发事件),但对于我需要的,它可能会起作用。如果有人有改进建议,请发帖子。我暂时不回答这个问题。