ES6代理的扩展方法有效,但带有TypeError

时间:2018-08-02 06:57:34

标签: javascript ecmascript-6 proxy

通过ES6代理实现扩展对象方法的功能,但具有TypeError如下:

const extendMethod = (obj) => (key) => (f) => {
    const handler = {
        get: (target, propKey, receiver) => {
            const targetValue = Reflect.get(target, propKey, receiver);
            return key === propKey
                ? f(target.valueOf())
                : (typeof targetValue === "function")
                    ? (...args) => Object(target.valueOf())[propKey](...args)
                    : targetValue;
        }
    };
    return new Proxy(obj, handler);
};

const a = { x: 5 };
const f = (target) => { console.log(target); };
const a1 = extendMethod(a)("log")(f);
a1.log(); //{x:5}
//TypeError: a1.log is not a function

如何修改代码以避免错误?谢谢。

1 个答案:

答案 0 :(得分:2)

该脚本期望a1.log评估为 function ,因为该脚本将继续被调用为a1.log();。但与行

? f(target.valueOf())

,运行f函数,然后将调用f的输出返回到外部。但是f的输出为undefined,因为(外部)f不返回任何内容。

抑制错误的一种方法是返回不执行任何操作的函数:

? (f(target.valueOf()), () => void 0)

const extendMethod = (obj) => (key) => (f) => {
    const handler = {
        get: (target, propKey, receiver) => {
            const targetValue = Reflect.get(target, propKey, receiver);
            return key === propKey
                ? (f(target.valueOf()), () => void 0)
                : (typeof targetValue === "function")
                    ? (...args) => Object(target.valueOf())[propKey](...args)
                    : targetValue;
        }
    };
    return new Proxy(obj, handler);
};

const a = { x: 5 };
const f = (target) => { console.log(target); };
const a1 = extendMethod(a)("log")(f);
a1.log(); //{x:5}

或者您可能只是访问 a1.log属性(将函数称为副作用)而不调用它:

const extendMethod = (obj) => (key) => (f) => {
    const handler = {
        get: (target, propKey, receiver) => {
            const targetValue = Reflect.get(target, propKey, receiver);
            return key === propKey
                ? f(target.valueOf())
                : (typeof targetValue === "function")
                    ? (...args) => Object(target.valueOf())[propKey](...args)
                    : targetValue;
        }
    };
    return new Proxy(obj, handler);
};

const a = { x: 5 };
const f = (target) => { console.log(target); };
const a1 = extendMethod(a)("log")(f);
a1.log; //{x:5}

如果外部f函数 did 返回一个函数(即,如果它是高阶函数),则您将能够正常使用a1.log()

const extendMethod = (obj) => (key) => (f) => {
    const handler = {
        get: (target, propKey, receiver) => {
            const targetValue = Reflect.get(target, propKey, receiver);
            return key === propKey
                ? f(target.valueOf())
                : (typeof targetValue === "function")
                    ? (...args) => Object(target.valueOf())[propKey](...args)
                    : targetValue;
        }
    };
    return new Proxy(obj, handler);
};

const a = { x: 5 };
const f = (target) => {
  console.log(target);
  return arg => {
    console.log('inner fn! ' + arg);
  };
};
const a1 = extendMethod(a)("log")(f);
a1.log('foo');