javascript - 设置包装函数的长度

标签 javascript ecmascript-5

我经常发现自己需要为各种目的在对象上包装一个函数。有没有一种优雅的方法可以在包装函数上保留原始函数的 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/

相关文章:

javascript - 使用 var that = this 时是复制还是引用?

javascript - 在转发到代理目标并将响应发送回客户端之前编辑 POST 参数

javascript - 如何将事件类添加到选定的列表项

javascript - 如何停止 Javascript forEach?

javascript - 原型(prototype)继承和静态方法

javascript - MongoDB 多重排序属性 : How is precedence determined?

javascript - AngularJS:点击后隐藏按钮

javascript - 如何作为加载程序无限重复动画?

javascript - 在 javascript 中应用 DefineProperties 的用例是什么?

javascript - Hapi 不从 Boom 错误返回数据属性