1

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
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Kinsi
  • 101
  • 2
  • 9
  • 1
    That is not how proxies are supposed to be created. Proxies are wrappers around objects, but not *types*. You are attempting to define a type that extends your base object (in your case `Array`), but proxies do not work by extending the prototype, so there is no inheritance chain. – poke Sep 17 '17 at 21:33
  • Possible duplicate of [Can I extend Proxy with an ES2015 class?](https://stackoverflow.com/questions/37714787/can-i-extend-proxy-with-an-es2015-class) – poke Sep 17 '17 at 21:40
  • I see, would explain why i couldnt just extend Proxy in the first place. 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) – Kinsi Sep 17 '17 at 21:40
  • Just for reference, here was an attempt of mine at messing around with extending arrays using proxy functionality you can check out [here](https://codereview.stackexchange.com/q/167537/73672). – Patrick Roberts Sep 17 '17 at 23:01

1 Answers1

3

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);
}
poke
  • 369,085
  • 72
  • 557
  • 602
  • This is genious! Although i made a small change to it: Within the customFunction i do my calls onto the created proxy instance itself, so that those calls would also get intercepted by the setter callback. I am aware this could cause infinite recursion, but i can live with that / will make sure it doesnt happen. Thanks a lot! – Kinsi Sep 17 '17 at 22:00
  • What is the benefit or what are you trying to solve? I am missing you gaining by using proxies? – james emanon Sep 23 '17 at 07:23
  • @jamesemanon Is that a general question what proxies are for? Or are you asking about this particular example? Obviously, this is just a constructed example to show the concept. – poke Sep 23 '17 at 07:43