我正在尝试使用JavaScript模仿更类似于类的继承模型,但在尝试将其与JavaScript代理的想法混合时遇到了问题。
总而言之,在我的类类型的定义中,我有一个带有语义的函数 _super()“当子类B的实例上的方法X调用_super()时,调用父类A上的方法X“:
Class A
.X() {...}
^
|
|
Class B
.X() {..._super(); ...}
我依靠函数 .caller.name方法来获取调用方法的名称(在我们的示例中,“X”)。然后我在父类上调用它。
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方法?
答案 0 :(得分:0)
唯一想到的是检查堆栈以找到不是“_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()
一般来说,依靠功能名称总是危险的(想想uglifiers等)。我想可以公平地说,如果没有某种预编译,你就不能在js中工作super
。注释