最近在看 underscore.js 的代码,一个函数 optimizeCb 无法理解
发布于 4 年前 作者 dd1994 3789 次浏览 最后一次编辑是 3 年前 来自 问答

就是这个 optimizeCb 函数,这是个独立的,在 underscore 里面非常基础的函数,后面的函数里经常用到它,

我直接把它贴上来吧

var optimizeCb = function(func, context, argCount) {
    if (context === void 0) return func;
    switch (argCount == null ? 3 : argCount) {
      case 1: return function(value) {
        return func.call(context, value);
      };
      case 2: return function(value, other) {
        return func.call(context, value, other);
      };
      case 3: return function(value, index, collection) {
        return func.call(context, value, index, collection);
      };
      case 4: return function(accumulator, value, index, collection) {
        return func.call(context, accumulator, value, index, collection);
      };
    }
    return function() {
      return func.apply(context, arguments);
    };
  };

文档介绍它说是

Internal function that returns an efficient (for current engines) version of the passed-in callback, to be repeatedly applied in other Underscore functions.

为什么这个函数可以返回一个 efficient version 呢?

3 回复

楼主除了它,还看过什么库呢?

上面一大段 switch 是为了在已知参数数量的情况下让 js 引擎做出优化(避免使用 arguments)。

等价如下:

var optimizeCb = function(func, context, argCount) {
    return function() {
        return func.apply(context, arguments);
    };
};

类似bind的功能。 https://www.zhihu.com/question/31439403

就是把调用的context(母对象)显式化。 比如 window.open 比 open 效率稍高。 因为,解释器看到window.open不需要自己去解析open是在哪个母对象执行的,一层层往上追溯损失效率。 现在为了open的简洁,而又不想失去这一点效率,就 var open = optimizeCB(open, window, …)

下面的代码就可以痛快地 open(…) open(…) open(…) 了。

当同一函数调用次数多的时候(比如底层函数),这个优化还是有意义的。

回到顶部