代理使用混乱 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
,例如注释。
我正在尝试使用 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
,例如注释。