Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/465.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 下划线中的优化CB是如何工作的?_Javascript_Performance_Underscore.js - Fatal编程技术网

Javascript 下划线中的优化CB是如何工作的?

Javascript 下划线中的优化CB是如何工作的?,javascript,performance,underscore.js,Javascript,Performance,Underscore.js,我一直在思考这个问题,从: 因此,显然,这种优化只适用于设置这个值的回调(这里称为上下文)。这与直接调用回调有什么不同?这是如何提高性能的 如果优化只对遗留的JS引擎有效,那也没关系。我很想知道 编辑 这个问题我可能不清楚。这就是我的意思。让我们举一个使用optimizeCb的例子: _.each = _.forEach = function(obj, iteratee, context) { iteratee = optimizeCb(iteratee, context); //R

我一直在思考这个问题,从:

因此,显然,这种优化只适用于设置
这个
值的回调(这里称为
上下文
)。这与直接调用回调有什么不同?这是如何提高性能的

如果优化只对遗留的JS引擎有效,那也没关系。我很想知道

编辑 这个问题我可能不清楚。这就是我的意思。让我们举一个使用optimizeCb的例子:

  _.each = _.forEach = function(obj, iteratee, context) {
    iteratee = optimizeCb(iteratee, context); //REMOVE this
    var i, length;
    if (isArrayLike(obj)) {
      for (i = 0, length = obj.length; i < length; i++) {
        iteratee(obj[i], i, obj);
        //REPLACE with iteratee.call(context, obj[i], i, obj);
      }
    } else {
      var keys = _.keys(obj);
      for (i = 0, length = keys.length; i < length; i++) {
        iteratee(obj[keys[i]], keys[i], obj);
      }
    }
    return obj;
  };
\uEach=\uForEach=函数(对象、迭代对象、上下文){
iteratee=optimizeCb(iteratee,context);//删除此
变量i,长度;
if(类isArrayLike(obj)){
对于(i=0,长度=obj.length;i
请参阅2条注释:
iteratee=optimizeCb(iteratee,context)//删除此
迭代对象(obj[i],i,obj)//替换为iteratee.call(上下文,obj[i],i,obj)。我知道争论很慢,应用也很慢。但我看不出参数调用vs应用在这里起到什么作用?我认为这两种方法没有区别

我认为关键问题是,如果回调被传递给某个下划线方法,那么签名就已经被知道了。例如,传入
的回调。每个
必须具有
函数(值、索引、集合)
。这个观察结果通过调用optimizeCb的方式得到证实:如果optimizeCb的调用者能够提供argCount参数(留空意味着它是3),那么它知道它是哪个签名


有人能再详细说明一下吗?非常感谢

他们这样做的三个原因:

  • 在旧的JavaScript引擎上访问
    参数
    伪数组的成本很高。真的很贵。比如,几个数量级的成本。:-)

    我不认为现代引擎会有太大的成本,特别是在严格模式下,这会消除
    参数
    和形式函数参数之间的实时联系

  • 正如a中所指出的,
    apply
    call
    慢。基于这一点,看起来大约是成本的一半到两倍。因此,与
    参数的数量级或两个数量级不同(回到今天),但速度更快

  • 如果
    context
    undefined
    ,则它们返回函数时保持不变(这是初始的
    If(context==void 0)return func;
    ),因此调用时根本不涉及
    。call
    。apply

  • 因此,这有两方面的作用:

    A) 如果回调不需要特定的
    this
    ,它将通过简单的函数调用直接使用回调。如果回调确实需要一个特定的
    this
    ,它们会创建一个函数,它们可以使用正确的
    this
    来调用该函数,这样可以避免传递
    上下文
    参数,并简化调用代码


    B) 通过定制包装函数,他们避免访问
    参数
    ,并使用
    apply
    处理常见数量的参数:使用1-4个参数的回调可以避免成本,使用0个或4个以上参数的回调会产生成本。

    调用
    的速度要快得多。我在想,因为它不必访问参数array@Moogs:您链接到的测试不是对苹果进行比较;我认为这一点是正确的:
    call
    apply
    还有一个明显的优势。@CharlesW.:上面加了第3条。
      _.each = _.forEach = function(obj, iteratee, context) {
        iteratee = optimizeCb(iteratee, context); //REMOVE this
        var i, length;
        if (isArrayLike(obj)) {
          for (i = 0, length = obj.length; i < length; i++) {
            iteratee(obj[i], i, obj);
            //REPLACE with iteratee.call(context, obj[i], i, obj);
          }
        } else {
          var keys = _.keys(obj);
          for (i = 0, length = keys.length; i < length; i++) {
            iteratee(obj[keys[i]], keys[i], obj);
          }
        }
        return obj;
      };