检测 class 的静态和实例方法的参数和 return 值
instrumenting arguments and return value of class's static and instance methods
我正在尝试记录输入参数和调用方法的 return 值。
class A {
constructor () {
this.x = 'x'
}
callinstance(x){
// i want to log above value of x without changing class code
if (typeof this.x !== 'string') throw new Error('this.x MUST_BE_STRING')
return x + 1
// i want to log value to be returned without changing code
}
}
A.callstatic = function(x){
// i want to log above value of x without changing class code
return x + 2
// i want to log value to be returned without changing code
}
A.a = 'a' // a static property should't be touched
// i can't change above code. i also cannot put a log in the actual methods
// now here is the soution, but runs into stack overflow. For obvious reasons.
const instrument = function(prop, static) {
return function (...args) {
if (!static) static = this
console.log(args) // here instrumenting inputs
const t = static[prop](...args)
console.log(t) // here instrumenting return values
return t
}
}
// overriding all the static methods
Object.getOwnPropertyNames(A).filter(p => typeof A[p] === 'function').forEach((prop) => {
A[prop] = instrument(prop, A)
})
// overriding all the instance methods
Object.getOwnPropertyNames(A.prototype).filter(p => typeof A.prototype[p] === 'function' && p !== 'constructor').forEach((prop) => {
A.prototype[prop] = instrument(prop)
})
// validation
console.log(A.callstatic(1))
console.log((new A()).callinstance(11))
console.log(A.a)
上面的解决方案由于显而易见的原因进入堆栈溢出。
任何解决方法来实现我的目标?不更改 class 代码?
PS : 这不是作业,我只是好奇有调试工具的解决方案。
您的问题是出现堆栈溢出错误,因为您重写了自己的方法
这意味着
/*
A[prop] = instrument(prop, A); <-- this turns into as followed (replacing A[prop] to method name)
function callinstance = () {
console.log(args) // here instrumenting inputs
const t = callinstance(...args) // <-- recursion happens here
console.log(t) /
}
你可以做一些变通来解决这个问题,创建函数的副本,并覆盖你的 class 方法,在你的自定义函数中调用 oldMethod
// overriding all the static methods
Object.getOwnPropertyNames(A).filter(p => typeof A[p] === 'function').forEach((prop) => {
let oldMethod = A[prop];
A[prop] = function(args) {
console.log(args);
let x = oldMethod(args);
console.log(x);
};
})
// overriding all the instance methods
Object.getOwnPropertyNames(A.prototype).filter(p => typeof A.prototype[p] === 'function' && p !== 'constructor').forEach((prop) => {
let oldMethod = A.prototype[prop];
A.prototype[prop] = function(...args) {
console.log(...args);
let x = oldMethod.call(this, ...args);
console.log(x);
};
})
我正在尝试记录输入参数和调用方法的 return 值。
class A {
constructor () {
this.x = 'x'
}
callinstance(x){
// i want to log above value of x without changing class code
if (typeof this.x !== 'string') throw new Error('this.x MUST_BE_STRING')
return x + 1
// i want to log value to be returned without changing code
}
}
A.callstatic = function(x){
// i want to log above value of x without changing class code
return x + 2
// i want to log value to be returned without changing code
}
A.a = 'a' // a static property should't be touched
// i can't change above code. i also cannot put a log in the actual methods
// now here is the soution, but runs into stack overflow. For obvious reasons.
const instrument = function(prop, static) {
return function (...args) {
if (!static) static = this
console.log(args) // here instrumenting inputs
const t = static[prop](...args)
console.log(t) // here instrumenting return values
return t
}
}
// overriding all the static methods
Object.getOwnPropertyNames(A).filter(p => typeof A[p] === 'function').forEach((prop) => {
A[prop] = instrument(prop, A)
})
// overriding all the instance methods
Object.getOwnPropertyNames(A.prototype).filter(p => typeof A.prototype[p] === 'function' && p !== 'constructor').forEach((prop) => {
A.prototype[prop] = instrument(prop)
})
// validation
console.log(A.callstatic(1))
console.log((new A()).callinstance(11))
console.log(A.a)
上面的解决方案由于显而易见的原因进入堆栈溢出。 任何解决方法来实现我的目标?不更改 class 代码?
PS : 这不是作业,我只是好奇有调试工具的解决方案。
您的问题是出现堆栈溢出错误,因为您重写了自己的方法 这意味着
/*
A[prop] = instrument(prop, A); <-- this turns into as followed (replacing A[prop] to method name)
function callinstance = () {
console.log(args) // here instrumenting inputs
const t = callinstance(...args) // <-- recursion happens here
console.log(t) /
}
你可以做一些变通来解决这个问题,创建函数的副本,并覆盖你的 class 方法,在你的自定义函数中调用 oldMethod
// overriding all the static methods
Object.getOwnPropertyNames(A).filter(p => typeof A[p] === 'function').forEach((prop) => {
let oldMethod = A[prop];
A[prop] = function(args) {
console.log(args);
let x = oldMethod(args);
console.log(x);
};
})
// overriding all the instance methods
Object.getOwnPropertyNames(A.prototype).filter(p => typeof A.prototype[p] === 'function' && p !== 'constructor').forEach((prop) => {
let oldMethod = A.prototype[prop];
A.prototype[prop] = function(...args) {
console.log(...args);
let x = oldMethod.call(this, ...args);
console.log(x);
};
})