【问题标题】:What's the best practice for passing a Javascript function with parameters without executing it?传递带参数的 Javascript 函数而不执行它的最佳实践是什么?
【发布时间】:2015-04-21 01:52:10
【问题描述】:

什么是传递带参数的 Javascript 函数而不执行它的最有效/最佳实践,为什么?这是我知道的选择:

创建一个匿名方法

jQuery("#target").click(function() {
    onTargetClick("myCoolParam");
});

function onTargetClick(coolParam) {
    // some epic code...
}

使用偏函数应用 (见:Partial function application

jQuery("#target").click(partial(onTargetClick, "myCoolParam"));

function onTargetClick(coolParam) {
    // some epic code...
}

function partial(func /*, 0..n args */) {
    var args = Array.prototype.slice.call(arguments).splice(1);
    return function() {
        var allArguments = args.concat(Array.prototype.slice.call(arguments));
        return func.apply(this, allArguments);
    };
}

编辑偏函数

function partial(func /*, 0..n args */) {
    var args = Array.prototype.slice.call(arguments, 1);
    return function() {
        var allArguments = args.concat(Array.prototype.slice.call(arguments));
        return func.apply(this, allArguments);
    };
}

感谢您的帮助。

【问题讨论】:

  • 使用.bind(),或者闭包
  • “最佳”问题与 Stack Overflow 无关,它们邀请基于意见的答案。可能有一种客观的方式来问这个问题,但是......
  • 肯定有客观的方式来回答这个问题。所有这样做的方法都有优点和缺点,其中许多是可衡量的,例如代码长度和执行时间。
  • @SamuelEdwinWard: :-) 许多基于意见的问题可以客观地回答。许多不是。 :-)
  • @T.J.Crowder 谢谢你的精确。我修复了帖子和我自己的代码:-)

标签: javascript anonymous-function partial-application


【解决方案1】:

视情况而定

在您的第一个示例中使用包装函数是直接的、易于阅读的、实用的,并且在现代引擎上不太可能产生与您使用它的上下文的闭包相关的令人不快的副作用(因为现代引擎在许多情况下优化平凡的闭包)。对于没有优化闭包的旧引擎,它可能会导致不必要地保存在内存中(并且仍然可以,使用更复杂的闭包;但是像你这样的引擎不使用evalnew Function , 或with,并且只引用了一个可能未在直接包含的上下文中声明的变量,是一个很好的优化候选者)。

使用 JavaScript 的 Function#bind 可以避免关闭问题;更简洁一点;并且在现代引擎上可能非常高效(而在需要填充的旧引擎上不会低效)。不过,它确实弄乱了this 的值,这可能是事件处理程序中的一个问题(尽管您在示例中没有使用this)。

使用像您的 partial 或 PrototypeJS 的 Function#curry 这样的函数还具有避免关闭问题和简洁的好处,不太可能高效,并使用 this 值赋予它们生成的功能。它们的缺点是不标准,因此您必须提供它们,并且阅读您的代码的人必须了解它们的作用。

任你选择。

【讨论】:

    【解决方案2】:

    我会使用Function.prototype.bind,它允许传递额外的参数:

    jQuery("#target").click(onTargetClick.bind(null, "myCoolParam"));
    

    【讨论】:

    • 那么,对于bind,绑定时还要指定this参数吗?
    • @SamuelEdwinWard:是的。 JavaScript 目前没有不需要 thisArg 的内置 curry 函数(这让我感到惊讶;当他们添加 PrototypeJS 多年来一直添加的 bind 时,他们选择不添加 curry,这是在现有技术中也有很好的表现)。
    • @T.J.Crowder JavaScript 目前没有不需要 thisArg 的内置 curry 函数。您是否暗示 ES6 中的箭头功能?
    • @dfsq:不,词汇this 绑定是一个单独的主题。我的意思是类似于 OP 的 partial 或 PrototypeJS 的 curry,这与 bind 不同的是使用 this 调用的结果函数。
    猜你喜欢
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 2013-01-07
    • 2011-10-15
    相关资源
    最近更新 更多