jeudi 2 août 2018

ES6 Proxy, calling a native method by `Reflect` and `apply`

Implementing a function to extend Object method by ES6 Proxy.

Basically to proxy get of Object method is troublesome, and I found a couple way to achieve that.

The most proper way it seems is to use Reflect and apply:

const targetValue = Reflect.get(target, propKey, receiver);
(...args) => targetValue.apply(Object(target.valueOf()), ...args) //[object Number] on  a1.toString()
                : targetValue;

However, this approach has a glitch when use of a native method such as toString(), it does not work properly.

On the other hand, there is a workaround approach, at least working for a simple scenario, not to use Reflect and apply which I feel not appropirate, and in fact, in some other complicated scenario, it generates an error:

TypeError: Object(...)[propKey] is not a function

So, I need to avoid to employ this workaround.

For the simple example as below, what is the way to show the string of the number:"5" by toString() method? Thanks.

const extendMethod = (i) => (key) => (f) => {
    const id = (value) => ({
        valueOf: () => value
    });
    const obj = (i !== Object(i)) //primitives
        ? id(i)
        : i;
    const handler = {
        get: (target, propKey, receiver) => {
            const targetValue = Reflect.get(target, propKey, receiver);
            return key === propKey
                ? (...args) => (f(target.valueOf()))(...args)
                : (typeof targetValue === "function")
                    //   ? (...args: undefined[]) => Object(target.valueOf())[propKey](...args)
                    ? (...args) => targetValue.apply(Object(target.valueOf()), ...args) //[object Number] on  a1.toString()
                    : targetValue;
        }
    };
    return new Proxy(obj, handler);
};
{
    const a = 5;
    const f = (target) => (arg) => {
        console.log(target, arg);
        return arg;
    };
    const a1 = extendMethod(a)("log1")(f);
    a1.log1("hello"); //5 'hello'
    const a2 = extendMethod(a1)("log2")(f);
    a2.log2("world"); //5 'world' 
    console.log(a1.toString() // "5" on `Object(target.valueOf())[propKey](...args)`
    //[object Number] //on `targetValue.apply(Object(target.valueOf()), ...args)`
    );
}




Aucun commentaire:

Enregistrer un commentaire