javascript - 检测类的静态方法和实例方法的参数和返回值

标签 javascript class instrumentation

我正在尝试记录所调用方法的输入参数和返回值。

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)

由于显而易见的原因,上述解决方案会出现堆栈溢出。 有什么解决方法可以实现我的目标吗?不改变类代码?

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) /
}

您可以采取一些解决方案来解决此问题,创建函数的副本,并覆盖您的类方法,在自定义函数中调用 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);
                };
})

关于javascript - 检测类的静态方法和实例方法的参数和返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59406661/

相关文章:

javascript - WebRTC onicecandidate : Am getting ICE candidates with sdpMid=audio only but not for video

javascript - Ember.js 在模型属性更改时如何更新链接到帮助程序 URL?

c++ - 我应该上课而不是重复的 get/set 语句吗?

c - GCC插件: copying function's arguments

javascript - 在 jQuery 中链接时 CSS 属性不起作用

JavaScript++ 运算符无法正常工作

python - 为什么回调没有被触发?

c++ - Unresolved external 尚未定义的构造函数?

android - 在 Android 中使用 Instrumentation 进行 GUI 测试

c++ - 使用二进制检测 Hook 函数