ES6类中的访问者组成

evo*_*box 0 javascript class composition mixins ecmascript-6

比方说,我有一个Thing,我想既类HideableOpenable.

使用类似于Douglas Crockford通过合成创建对象的方法,我已经能够从多个类"继承".

这种方法不适用于访问器(getter/setter).

我需要使用类,因为它是一个要求.我也发现我在类之间复制功能,但我不希望它们从基类继承.

有任何想法吗?

到目前为止我所取得的进展如下:

class Openable {

  constructor(isOpen = false) {
    this._isOpen = isOpen;
  }

  get isOpen() {
    return this._isOpen + ' is stupid.';
  }

  set isOpen(value) {
    this._isOpen = value;
  }

}


class Hideable {

  constructor(isHidden = false) {
    this._isHidden = isHidden;
  }

  get isHidden() {
    return this._isHidden + ' is stupid.';
  }

  set isHidden(value) {
    this._isHidden = value;
  }

}


class Thing {

  constructor(config) {
    let { isOpen, isHidden } = config;

    let openable = new Openable(isOpen);
    this.isOpen = openable.isOpen;

    let hideable = new Hideable(isHidden);
    this.isHidden = openable.isHidden;
  }

}


let thing = new Thing({
  isOpen: true,
  isHidden: false
});
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 6

因为isOpen并且isHidden访问者,您不能只抓取它们的副本,您必须在需要时访问它们.

不过,你可以创建自己的 isOpen,isHidden使用底层的:

let openable = new Openable(isOpen);
Object.defineProperty(this, "isOpen", {
    get: () => openable.isOpen,
    set: value => {
        openable.isOpen = value;
    }
});

let hideable = new Hideable(isHidden);
Object.defineProperty(this, "isHidden", {
    get: () => hideable.isHidden,
    set: value => {
        hideable.isHidden = value;
    }
});
Run Code Online (Sandbox Code Playgroud)

关于Babel的REPL的实例

当然,如果你经常这样做,你需要有一个工作函数来设置它而不是一直重新输入它:

function wrapProperty(dest, src, name) {
    Object.defineProperty(dest, name, {
        get: () => src[name],
        set: value => { src[name] = value; }
    });
}
Run Code Online (Sandbox Code Playgroud)

(或者通过抓取属性描述符并更新它来实现)

然后:

wrapProperty(this, openable, "isOpen");
wrapProperty(this, hideable, "isHidden");
Run Code Online (Sandbox Code Playgroud)

我会质疑你必须使用的class要求OpenableHideable.他们看起来更像是我的混合物.