问题 Function.prototype.bind()总是很慢吗?


我正在编写一个开源的JavaScript库,我使用 .bind() 方法很重,因为我有一个想法,面向对象的代码看起来更清晰。 (但值得商榷

A1:

var that = this;

setTimeout(function () {
    that.method();
}, 0);

VS

B1:

setTimeout(this.method.bind(this), 0);

或者,更实用的代码部分

A2:

remoteDataSource.getData(function (a, b, c, d) {
     obj.dataGetter(a, b, c, d);
})

vs B2:

remoteDataSource.getData(obj/* or prototype */.dataGetter.bind(obj));

我使用的是非原生的 bind 对于旧浏览器,一切都很完美,直到我打开一个 绑定的jsperf基准

它看起来像代码使用 bind 是100倍慢。现在,在重写我的所有库之前,我对那些熟悉javascript引擎的人有一个问题:

是否有可能成为新功能, bind 将得到优化  很快,还是因为JavaScript架构限制而没有机会?


5956
2017-09-19 12:59


起源

发现了一个相关问题 stackoverflow.com/questions/8656106/... - Dan
最好的解决方案之一是: jsperf.com/bind-vs-emulate/6 - Dan


答案:


首先,修复jsperf http://jsperf.com/bind-vs-emulate/13

=您不应在基准测试中重新创建静态函数。这是不现实的,因为在实际代码中,静态函数只创建一次。

你可以看到 var self = this 模式仍然快约60%。但它需要内联函数定义,因为您可以从任何地方进行绑定,因此具有更好的可维护性。


嗯不,内置的绑定语义是荒谬的错综复杂的。

当我绑定时,我只想要这个:

function bind(fn, ctx) {
    return function bound() {
        return fn.apply(ctx, arguments);
    };
}

如果我想预先应用参数或使用一些深层构造黑魔法,我会想要一个完全不同的功能。我不知道为什么任何这个都包含在bind中。

<rant>顺便说一句,同样的问题在于ES5中引入的几乎所有内容,通过强制实现来处理一些与实际中任何人都不相关的理论边缘情况来惩罚常见情况。下一个语言版本继续在同一条路径上。</ rant>

模拟绑定甚至根本不会尝试模拟绑定。即使你试图模仿它,你也无法做到 完全做到这一点,这是不公平的。

所以在其他条件相同的情况下*内置绑定不能比仅仅绑定的常识自定义绑定更快。

*在JIT中,用户代码对内置代码没有明显的缺点。实际上,SM和V8都实现了许多内置函数 在Javascript中。


12
2017-09-20 05:46



今天在Firefox中运行测试显示 .bind() 在Chrome中速度最快但速度最慢。你提出了许多好点,但内置绑定的结论不能更快似乎不对。虽然绑定函数确实有一定的开销,但它也消除了一些开销。特别是,它不需要调用不同的函数,而是共享原始函数的主体,因此它非常接近于调用原始函数。它也不需要遍历变量范围来获取它所绑定的值。所以我认为它总是归结为实现细节而非规范。
很抱歉对旧答案的评论,但有人提到了它。


目前,2013年底,将实施最佳解决方案 手工制造 的版本 Function.prototype.bind 并使用您自己的javascript代码覆盖供应商的“原生”(不是真正的原生)方法,或使用您自己的 myBind

Function.prototype.apply 相当快,并且数组切片,连接和移位很慢,所以你最好使用 apply 相反,如果 bind,或最小化参数操纵 myBind 功能。这将使您没有预填充参数的功能。

所以我认为没有必要将所有内容重写回闭包(丑陋 var that = this;)。让javascript的功能性获胜。

这里有更多细节和工作代码示例:

http://jsperf.com/function-bind-performance/4

http://jsperf.com/function-bind-performance/5

http://jsperf.com/bind-vs-emulate/4  .. 10。

总结:找到的解决方法并不是那么糟糕。勇敢地使用它们。如果你没有使用功能齐全 bind,不要离原始概念太远,因为我没有发现它没有在C中实现的原因。这是一个时间问题。


0
2017-09-19 13:51



仍然在瓶颈中使用闭包 - Dan