我经常发现自己需要将一个函数包装在一个对象上以用于各种目的。是否有一种优雅的方法来保留包装函数上原始函数的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)将函数动态生成为字符串并{(1}} / eval
或(2)具有巨大的代理函数数组不同长度,并选择对应正确长度的代理功能。这对我来说似乎不是一个优雅的解决方案,并且似乎是一个合理的请求,能够使用任意new Function
创建一个函数,而不用指定函数中的每个参数。
似乎length
能够在内部执行此操作:
bind
这会创建一个包含原始长度的包装函数!这正是我想要自己做的事情。
还有其他办法吗?
答案 0 :(得分:1)
我喜欢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");
}
}
答案 1 :(得分:0)
如果你需要以相同的方式获取包装和解包函数的长度,但可以处理不使用length属性,这样的事情可能会有所帮助:
Function.prototype.mylengthf = function() {
return this.mylength | this.length;
};
var x = {
a: function(arg1, arg2) { /* do something */ },
b: function(arg1, arg2, arg3) { /* do something else */ }
};
function wrap(obj) {
var original = obj.a;
obj.a = function wrapper() {
console.log('a called');
original.apply(this, arguments);
};
obj.a.mylength = original.length;
}
log(x.a.length); // => 2
wrap(x);
log(x.a.length); // => 0
log(x.a.mylengthf()); // => 2
log(x.b.mylengthf()); // => 3