我经常发现自己需要为各种目的在对象上包装一个函数。有没有一种优雅的方法可以在包装函数上保留原始函数的 length
属性?
例如:
var x = {
a: function(arg1, arg2) { /* do something */ }
};
function wrap(obj) {
var original = obj.a;
obj.a = function wrapper() {
console.log('a called');
original.apply(this, arguments);
};
}
x.a.length; // => 2
wrap(x);
x.a.length; // => 0
我想做什么:
var x = {
a: function(arg1, arg2) { /* do something */ }
};
function wrap(obj) {
var original = obj.a;
obj.a = function wrapper() {
console.log('a called');
original.apply(this, arguments);
};
obj.a.length = original.length;
}
x.a.length; // => 2
wrap(x);
x.a.length; // => 2 (actual still 0)
但是,这不起作用,因为 length
不可写。
目前我唯一能想到的解决方案是 (1) 动态生成函数作为字符串和 eval
/new Function
或 (2)拥有大量不同长度的代理函数,并选择与正确长度对应的代理函数。这对我来说似乎不是一个优雅的解决方案,并且能够创建具有任意 length
而不指定函数中每个参数的函数似乎是一个合理的要求。
似乎 bind
能够在内部完成此操作:
function a(b, c) { }
a.bind(null).length; // => 2
这将创建一个具有原始长度的包装函数!这正是我希望自己能够做到的。
还有其他办法吗?
最佳答案
我喜欢 eval(...) 方法,因为它很简单。
function wrap(obj) {
var f = obj.fun.toString();
f = f.replace("{", "{ alert('wrapper'); ");
obj.fun = eval('['+f+']')[0];
}
您可以将其扩展为具有表示包装函数的 wrap 的第二个参数,并通过字符串操作将它们组合起来变得更加有趣。
如果您的目标是包装透明,那么只需使用编程语言的动态功能即可。
如果您愿意对 JavaScript 文件进行额外处理,您可以内置热补丁/包装。
var x = {
a: function(arg1, arg2) {
(x._a || (function(){}))();
... do actual function stuff ...
}
}
function wrap(obj) {
obj._a = function() {
console.log("ok");
}
}
关于javascript - 设置包装函数的长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13051332/