Is there a away to Bind a Proxy object to the ES6 class constructor?

Viewed 234

In ES5^ I can create a proxy object and bind it to the other functions constructors, see what I want to do in the example below:

function X() {
  this.x = `${this.anyAttr} it's a trap`;
}

function Y() {
  this.y = `${this.anyAttr} do the barrel roll`;
}

function Z(...a) {
  const proxy = new Proxy(this, { 
    get(target, key) {
      if (target[key]) {
        return Reflect.get(target, key);
      }
      return "FROM Z:";
    }
  });
  X.apply(proxy, a);
  Y.apply(proxy, a);

  return proxy;
}

const obj = new Z();

console.log(obj.someAttr) // FROM Z:
console.log(obj.x)        // FROM Z: it's a trap
console.log(obj.y)        // FROM Z: do the barrel roll

I want to do the same thing, but with the ES6 Class syntax, but the apply method can't be used with ES6 classes, see the example below:

class X {
    constructor() {
        this.x = `${this.anyAttr} it's a trap`
    }
}

class Y {
    constructor() {
        this.y = `${this.anyAttr} do the barrel roll`
    }
}

function Z(...a) {
    const proxy = new Proxy(this, { 
        get(target, key) {
             if (target[key])
                return Reflect.get(target, key)
             return "FROM Z:"
        }
    })

    X.apply(proxy, a) // Uncaught TypeError: Class constructor X cannot be invoked without 'new' at new Z
    Y.apply(proxy, a) // Uncaught TypeError: Class constructor Y cannot be invoked without 'new' at new Z
    
    return proxy;
}

const obj = new Z()

To be specific, I need to mix classes, but before construct the superclasses I need to link a proxy object to do some black magic, so...

Is there a way to do something similar to the first example but using ES6 Classes?

1 Answers

I'd recommend re-designing your mixins to be higher-order classes like this:

const X = (Base) => class extends Base {
  constructor(...args) {
    super(...args);
    this.x = `${this.anyAttr} it's a trap`;
  }
};

const Y = (Base) => class extends Base {
  constructor(...args) {
    super(...args);
    this.y = `${this.anyAttr} do the barrel roll`;
  }
};

const Z = Y(X(class {
  constructor(...args) {
    return new Proxy(this, {
      get(target, key, receiver) {
        if (Reflect.has(target, key, receiver))
          return Reflect.get(target, key);
        return "FROM Z:";
      }
    });
  }
}));

const obj = new Z();

console.log(obj.someAttr); // FROM Z:
console.log(obj.x); // FROM Z: it's a trap
console.log(obj.y); // FROM Z: do the barrel roll

Related