我想制作一个通用函数包装器(例如)打印被调用函数及其参数。
通过arguments
准数组和简单的调用,这样做很容易。例如:
function wrap(target, method) {
return function() {
console.log(Array.prototype.slice.call(arguments).join(', '));
return method.apply(target, arguments);
}
}
但是,这种做法当然完全失去了被调用函数的元数(如果你不知道,可以通过它的长度
)获得JavaScript函数的元数(参数个数) > 属性(property))。
有没有办法动态创建一个包装函数,将包装函数的参数复制到它自己?
我考虑过创建一个新的 Function object ,但我看不到任何静态提取参数列表的方法,因为 arguments
property已弃用。
最佳答案
这是一个使用 Function
的解决方案:
// could also generate arg0, arg1, arg2, ... or use the same name for each arg
var argNames = 'abcdefghijklmnopqrstuvwxyz';
var makeArgs = function(n) { return [].slice.call(argNames, 0, n).join(','); };
function wrap(target, method) {
// We can't have a closure, so we shove all our data in one object
var data = {
method: method,
target: target
}
// Build our function with the generated arg list, using `this.`
// to access "closures"
f = new Function(makeArgs(method.length),
"console.log(Array.prototype.slice.call(arguments).join(', '));" +
"return this.method.apply(this.target, arguments);"
);
// and bind `this` to refer to `data` within the function
return f.bind(data);
}
编辑:
这是一个更抽象的解决方案,它解决了闭包问题:
function giveArity(f, n) {
return new Function(makeArgs(n),
"return this.apply(null, arguments);"
).bind(f);
}
还有一个更好的,它在调用时保留上下文:
function giveArity(f, n) {
return eval('(function('+makeArgs(n)+') { return f.apply(this, arguments); })')
}
用作:
function wrap(target, method) {
return giveArity(function() {
console.log(Array.prototype.slice.call(arguments).join(', '));
return method.apply(target, arguments);
}, method.length)
}
关于javascript - 覆盖函数的元数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13271474/