我想知道在 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)
也许还有另一种方法来实现这一点,而不是使用事件侦听器,但我不知道。
谢谢!
一种方法是使用代理来创建“跟踪”对象,您可以在其中拦截任何方法调用:
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)