Kinsi
Kinsi

Reputation: 111

Extending Array / Proxy in ES6 correctly?

Currently trying to make a custom implementation of Array / Object (Would end up being pretty similar i suppose) and have stumbled upon an issue that is driving me crazy.

As you can see, b is only an instanceOf Array, even though its created from custom class CachedArray, thus my custom function testPush is not defined, and i cant for the sake of everything find what is the issue.

Using Nodejs 6

function _setKey(target, key, value) {
  console.log('Setting value', key, 'to', value);
  target[key] = value;
  return true;
}

class ExtendableProxy {
  constructor(a, b) {
    return new Proxy(a, b);
  }
}

class CachedArray extends ExtendableProxy {
  constructor(redis, options) {
    let RawArray = [];

    super(RawArray, {
      set: _setKey
    });

    this._rawArray = RawArray;

    this.redis = redis;
    this.options = options;
  }

  testPush() {
    this.push('Its me');
  }
}

var b = new CachedArray();

console.log('b instanceof CachedArray', b instanceof CachedArray); //false
console.log('b instanceof ExtendableProxy', b instanceof ExtendableProxy); //false
console.log('b instanceof Proxy', b instanceof Proxy); //false
console.log('b instanceof Array', b instanceof Array); //true

b.push('Hello.'); //Works just fine, _setKey is called and executed correctly
b.testPush(); //TypeError: b.testPush is not a function

Upvotes: 2

Views: 4003

Answers (1)

poke
poke

Reputation: 387745

Is there an alternative to what i am trying to achieve? Essentially i need an array with some extra functions of mine, which however has a Proxy connected to it, so that i can further process any writes happening to the instance of my class (So, the Array)

Well, the proxy has a handler that allows you to hook into every kind of interaction with the proxied object. So you should use that to inject any additional methods you want to add to the proxied object. For example, just provide the get so it returns a custom function instead of relaying the call back to the target:

function createCachedArray(arr) {
    const customFunctions = {
        testPush() {
            this.push('It’s me');
        },
    };

    return new Proxy(arr, {
        set (target, property, value) {
            console.log(`Setting value ${property} to ${value}`);
            target[property] = value;
            return true;
        },
        has (target, property) {
            return property in customFunctions || property in target;
        },
        get (target, property) {
            if (typeof property === 'string' && property in customFunctions) {
                return customFunctions[property].bind(target);
            }
            else {
                return target[property];
            }
        },
    });
}

let a = [1, 2, 3];
let b = createCachedArray(a);

b.push('foo');
b.testPush();
for (const x of b) {
    console.log(x);
}

Upvotes: 4

Related Questions