Javascript:知道调用了哪个对象函数

eal*_*lef 4 javascript object

我想知道在 javascript 中是否有一种方法可以在调用任何对象函数时得到通知。

例如,我想做如下事情:

如果我有这样的对象:

myObject = {
    functionOne: function(argumentOne) {
        // do some stuff
    },

    functionTwo: function() {
        // do some stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

并添加一个监听器(或其他任何东西来跟踪在这个对象上发生的动作):

myObject.addEventListener('onFunctionCall', functionHasBeenCalled);
Run Code Online (Sandbox Code Playgroud)

当我打电话时:

myObject.functionOne('hello');
Run Code Online (Sandbox Code Playgroud)

使用有关被调用函数的信息触发的侦听器处理程序:

functionHasBeenCalled(calledFunctionData) {
    console.log(calledFunctionData.functionName + ' has been called');
    console.log('with argument: ' + calledFunctionData.functionArgument);
}
Run Code Online (Sandbox Code Playgroud)

控制台输出为:

functionOne has been called
with argument: hello
Run Code Online (Sandbox Code Playgroud)

也许还有另一种方法来实现这一点,而不是使用事件侦听器,但我不知道。

谢谢!

nem*_*035 5

一种方法是使用代理来创建“跟踪”对象,您可以在其中拦截任何方法调用:

function trackMethodCalls(obj) {
  const handler = {
    // anytime we do obj.someMethod
    // we actually return the interceptedMethod instead
    get(target, propKey, receiver) {
      
      const method = target[propKey];

      // we only do something special if we're working with a function
      // on the object. If the property isn't a function we can just return
      // it as normal.
      if (typeof method !== 'function') {
        return method;
      }

      return function interceptedMethod(...args) {
        const result = method.apply(this, args);

        console.log(
          `${propKey}(${args.join(",")}) = ${JSON.stringify(result)}`
        );

        return result;
      };
    }
  };
  return new Proxy(obj, handler);
}

const obj = {
  val: 2,
  double(x) {
    return this.val * x;
  }
};

const trackedObj = trackMethodCalls(obj);

trackedObj.double(4);
Run Code Online (Sandbox Code Playgroud)

如果你想改变一个对象而不是通过代理检测它,你应该直接覆盖它的方法:

function addTrackedMethods(obj) {
  for (const [methodName, method] of Object.entries(obj).filter(
    ([, method]) => typeof method === "function"
  )) {
    obj[methodName] = function interceptedMethod(...args) {
      const result = method.apply(this, args);

      console.log(
        `${methodName}(${args.join(",")}) = ${JSON.stringify(result)}`
      );

      return result;
    };
  }
}

const obj = {
  val: 2,
  double(x) {
    return this.val * x;
  }
};

addTrackedMethods(obj);

obj.double(4);
Run Code Online (Sandbox Code Playgroud)

  • 我的意思是当您事先不知道将访问哪些属性时。如果您只是包装一个可以枚举其方法的现有对象,则不需要代理来捕获任意属性。 (2认同)