代理使用混乱 function.caller.name

Proxy usage messes up function.caller.name

我正在尝试使用 JavaScript 来模仿更 class 的继承模型,但是在尝试将其与 JavaScript 代理的想法混合时遇到了问题。

长话短说,在我的 Class 类型的定义中,我有一个函数 _super() 具有语义 "when method X on an instance of subclass B invokes _super(), call method X on parent class A":

Class A
   .X() {...}
   ^
   |
   |
Class B
   .X() {..._super(); ...}

我依靠 function.caller.name 方法来获取调用方法的名称(在我们的示例中,"X")。然后我在父 class.

上调用它
const Class = {
...
    _super: function _super(...args) {
      // Get a handle on the function in which this function is invoked:
      const callerMethod = _super.caller.name;
      ...
    },
...
};

这工作正常。当我在我的 Class 构造之上添加一个 Proxy 对象时,问题就开始了(我想捕获一些方法调用)。

function traceMethodCalls(obj) {
  const handler = {
    get(target, propKey, receiver) {
      const origMethod = target[propKey];
      return function (...args) {
        // Do stuff
      };
    },
  };
  return new Proxy(obj, handler);
}

现在,_super() 方法中的function.caller 是代理处理程序对象中的匿名函数(显然...),这会打乱程序流程。

我的问题:有没有办法规避这个问题?或者有不同的想法?还是我必须完全放弃 *.caller.name 方法?

唯一想到的是检查堆栈以找到第一个不是“_super”的东西。 IMO 相当愚蠢,但就是这样。

const Class = {

    _super: function _super(...args) {
        let callerMethod;

        let s = (new Error)
            .stack.split('\n')
            .slice(2);
        while (s.length && s[0].includes('_super'))
            s.shift();

        let m = (s[0] || '').match(/^\s*at\s\w+\.(\w+)/);
        callerMethod = m ? m[1] : null;
        console.log('super call [%s]', callerMethod)
    },

    foo: function () {
        this._super()
    }
};


function traceMethodCalls(obj) {
    const handler = {
        get(target, propKey, receiver) {
            const origMethod = target[propKey];
            let f = {
                [propKey]: function (...args) {
                    console.log('tracing', propKey)
                    origMethod.bind(this)()
                }
            };
            return f[propKey];
        },
    };
    return new Proxy(obj, handler);
}

obj = Object.create(Class)
obj.foo()
traced = traceMethodCalls(obj)
traced.foo()

一般来说,依赖函数名总是很危险的(想想丑陋的人等)。我想可以公平地说,如果没有某种预编译,你就无法在 js 中工作 super,例如注释。