13

我正在编写一个开源 javascript 库,并且我.bind()大量使用方法,因为我认为面向对象的代码看起来更清晰。(虽然有争议

例子

A1:

var that = this;

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

对比

B1:

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

或者,更实用的代码部分

A2:

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

与 B2:

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

bind我为旧版浏览器使用了非本机,一切都很完美,直到我为 bind 打开了一个 jsperf 基准

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

作为一个新特性,是否有可能bind很快得到优化,或者由于 JavaScript 架构限制而没有机会?

4

2 回答 2

14

首先,修复了 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 中实现了许多内置功能。

于 2013-09-20T05:46:48.193 回答
0

目前,到 2013 年底,最好的解决方案将是实现手工制作的版本,Function.prototype.bind或者用您自己的 javascript 代码覆盖供应商的“本机”(不是真正的本机)方法,或者使用您自己的myBind.

Function.prototype.apply相当快,并且数组切片,连接和移位很慢,因此您最好使用applyifbind或最小化函数中的参数操作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.

总结:发现的变通方法还不错。勇敢地使用它们。如果您使用 not fully features bind,请不要离最初的概念太远,因为我没有发现它尚未在 C 中实现的原因。这是时间问题。

于 2013-09-19T13:51:31.433 回答