我很感激,如果有人能告诉我如何拦截javascript中的函数调用。 我知道可以使用代理。
例如,我尝试使用下面的代码来拦截它,但现在我想拦截toDataURL()
。为了调用toDataURL,你需要首先创建一个canvas元素。所以,现在我想知道如何定义代理来拦截toDataURL()
。
拦截它的示例代码:
window.x = 0;
let calls = (function(){
let canvas = document.createElement('canvas');
let fun = canvas.toDataURL;
canvas.toDataURL = function(){
window.x++;
return fun.apply(document, arguments);
}
return ()=>calls;
})();
答案 0 :(得分:0)
虽然总是应该有一个很好的理由来修改标准类型的标准方法,但JS中方法修改的基本方法是包装。有人甚至可能会考虑标准化Function.prototype[before|after|around|afterThrowing|afterFinally]
。然后修改任何给定的方法或函数将像下一个提供的示例一样简单,也可能是OP正在寻找的答案......
(function (Function) {
var
isFunction = function (type) {
return (
(typeof type == "function")
&& (typeof type.call == "function")
&& (typeof type.apply == "function")
);
},
getSanitizedTarget = function (target) {
return ((target != null) && target) || null;
};
Function.prototype.before = function (handler, target) { // before
target = getSanitizedTarget(target);
var proceed = this ;
return (isFunction(handler) && isFunction(proceed) && function () {
var args = arguments;
handler.call((target || this), args);
return proceed.apply((target || this), args);
}) || proceed;
};
Function.prototype.after = function (handler, target) { // afterReturning
target = getSanitizedTarget(target);
var proceed = this ;
return (isFunction(handler) && isFunction(proceed) && function () {
var ret, args = arguments;
ret = proceed.apply((target || this), args);
handler.call((target || this), ret, args);
return ret;
}) || proceed;
};
Function.prototype.around = function (handler, target) { // around
target = getSanitizedTarget(target);
var proceed = this ;
return (isFunction(handler) && isFunction(proceed) && function () {
return handler.call((target || this), proceed, handler, arguments);
}) || proceed;
};
}(Function));
function modifyCanvasToDataUrlAfter(returnValue, thisArgs) {
console.log('modifyCanvasToDataUrlAfter :: thisArgs : ', thisArgs);
console.log('modifyCanvasToDataUrlAfter :: returnValue : ', returnValue);
}
HTMLCanvasElement.prototype.toDataURL = HTMLCanvasElement.prototype.toDataURL.after(modifyCanvasToDataUrlAfter);
var elmToJpgLow = document.getElementById('canvasToLowResolutionJpg');
var elmToJpgMedium = document.getElementById('canvasToMediumResolutionJpg');
console.log("elmToJpgLow.toDataURL('image/jpeg', 0.1) : ", elmToJpgLow.toDataURL('image/jpeg', 0.1));
console.log('elmToJpgLow.toDataURL : ', elmToJpgLow.toDataURL);
console.log("elmToJpgMedium.toDataURL('image/jpeg', 0.1) : ", elmToJpgMedium.toDataURL('image/jpeg', 0.5));
console.log('elmToJpgMedium.toDataURL : ', elmToJpgMedium.toDataURL);
.as-console-wrapper { max-height: 100%!important; top: 0; }
<canvas id="canvasToLowResolutionJpg" width="5" height="5"></canvas>
<canvas id="canvasToMediumResolutionJpg" width="5" height="5"></canvas>
<强> 修改 强>
基于Proxy
的方法可能类似于以下提供的示例...
const canvasToDataUrlModifier = {
apply: function(target, thisArg, argumentsList) {
let returnValue = target.apply(thisArg, argumentsList);
console.log('toDataUrlAfterModifier :: argumentsList : ', argumentsList);
console.log('toDataUrlAfterModifier :: returnValue : ', returnValue);
return returnValue;
}
};
var elmToJpgLow = document.getElementById('canvasToLowResolutionJpg');
var elmToJpgMedium = document.getElementById('canvasToMediumResolutionJpg');
var proxyToJpgLow = new Proxy(elmToJpgLow.toDataURL, canvasToDataUrlModifier);
var proxyToJpgMedium = new Proxy(elmToJpgMedium.toDataURL, canvasToDataUrlModifier);
console.log("proxyToJpgLow.call(elmToJpgLow, 'image/jpeg', 0.1) : ", proxyToJpgLow.call(elmToJpgLow, 'image/jpeg', 0.1));
console.log("proxyToJpgMedium.call(elmToJpgMedium, 'image/jpeg', 0.5) : ", proxyToJpgMedium.call(elmToJpgMedium, 'image/jpeg', 0.5));
.as-console-wrapper { max-height: 100%!important; top: 0; }
<canvas id="canvasToLowResolutionJpg" width="5" height="5"></canvas>
<canvas id="canvasToMediumResolutionJpg" width="5" height="5"></canvas>