【问题标题】:Why is this javascript necessary?为什么这个javascript是必要的?
【发布时间】:2014-03-30 18:02:55
【问题描述】:

我在阅读 pallet.js 的源代码时遇到了这个问题。

var ret = (function(proto) {
  return {
    slice: function(arr, opt_begin, opt_end) {
      return proto.slice.apply(arr, proto.slice.call(arguments, 1));
    },
    extend: function(arr, arr2) {
      proto.push.apply(arr, arr2);
    }
  };
})(Array.prototype);
var slice = ret.slice;
var extend = ret.extend;

为什么这是必要的?为什么他们不能简单地写这个:

var slice = function(arr,opt_begin,opt_end) {
  return Array.prototype.slice.apply(arr,[opt_begin,opt_end]));
}
var extend = function(arr,arr2) {
  return Array.prototype.push.apply(arr,arr2);
}

编辑 1:

针对重复的问题。我不认为这是重复的,但这个问题确实解决了我的问题。所以这是一个优化。但是不是每个都只评估一次吗?那么对于两个函数调用,这里真的有显着的改进吗?

另外,如果我们担心性能,为什么我们调用proto.slice.call(arguments,1) 而不是手动构造两个元素的数组[opt_begin,opt_end],切片更快吗?

【问题讨论】:

标签: javascript


【解决方案1】:

因为语法实在是太酷了。另外,您可以通过告诉自己它更干燥来合理化它的使用。您不必输入两次Array.prototype

【讨论】:

  • 它也不会为您节省属性查找,因为闭包无论如何都会添加 1 个属性查找。
【解决方案2】:

我无法确定该代码背后的原始原理是什么(只有作者知道),但我可以看到一些差异:

  • proto 是一个封闭的局部变量,而 Array 是一个全局变量。足够智能的 Javascript 引擎可以优化访问,因为 proto 永远不会更改,因此它甚至可以通过值而不是引用来捕获。 proto.slice 可能比 Array.prototype.slice 更快,因为需要更少的查找。

  • opt_beginopt_end 传递为undefined 与一般不传递它们不同。被调用的函数可以知道是否传递了一个参数并且恰好是undefined,或者它是否没有传递。使用proto.slice.call(arguments, 1) 可确保参数仅在实际传递给闭包时才传递给slice

【讨论】:

  • 啊!现在调用 slice 而不是自己定义它非常有意义。但是Array.prototype.sliceproto.slice 节省了一次查找(不确定这是否是正确的词),因为我们必须首先将Array.prototype 作为参数传递。然后我们调用ret.sliceret.extend,它们本身就是两个查找......那么这段代码不会运行得更慢吗?
  • 创建闭包的查找只进行一次。在您的示例中,每次调用函数时都会完成。
  • 最后一个问题...如果我们将 proto 设为局部变量,我在这个测试中的逻辑有什么问题吗? jsperf.com/palette-js-perf-test
  • @Crackers:在我看来,您正在衡量创建包装器的时间(只做一次的事情),而不是实际调用它们的时间。
  • 你是完全正确的。我更新了测试。它在我的浏览器上显示两者的性能没有重大差异。 jsperf.com/palette-js-perf-test
猜你喜欢
  • 1970-01-01
  • 2013-07-28
  • 2010-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-03
  • 1970-01-01
  • 2020-04-01
相关资源
最近更新 更多