JavaScript的数组反转

7

Javascript中的array.reverse()方法究竟是如何工作的?它会遍历数组并交换每个元素吗?如果是这样,那么交换大小为n的数组需要花费O(n)的时间吗?

我问这个问题的原因是想知道array.reverse()是否与以下方法相同:

for(var i = 0; i < a.length / 2; i++) {
  var holder = a[i];
  a[i] = a[a.length - 1 - i];
  a[a.length - 1 - i] = holder;
}

注意:如果我发布的Javascript代码是错误的,抱歉,因为现在已经很晚了。

编辑: 已将a.length更正为a.length / 2


2
这是不正确的,因为通过完全遍历数组,你会将所有元素交换两次并返回到原始数组。使用 a.length / 2(a.length 除以 2 的整数除法)。 - xanatos
2个回答

6

具体工作方式的完整细节,请阅读规范中相关的部分。这里是算法:

  1. 让O成为将this值作为参数传递后调用ToObject的结果。

    1. 让lenVal成为使用O作为[[Get]]内部方法的参数"length"时的结果。
    2. 让len成为ToUint32(lenVal)的结果。
    3. 让middle成为floor(len/2)的结果。
    4. 让lower成为0。
    5. 重复执行以下操作,直到lower ≠ middle

      1. 让upper成为len−lower −1的结果。
      2. 让upperP成为ToString(upper)的结果。
      3. 让lowerP成为ToString(lower)的结果。
      4. 让lowerValue成为使用O作为[[Get]]内部方法的参数lowerP时的结果。
      5. 让upperValue成为使用O作为[[Get]]内部方法的参数upperP时的结果。
      6. 让lowerExists成为使用O作为[[HasProperty]]内部方法的参数lowerP时的结果。
      7. 让upperExists成为使用O作为[[HasProperty]]内部方法的参数upperP时的结果。
      8. 如果lowerExists为true且upperExists为true,则

      9. 使用lowerP、upperValue和true作为参数调用O的[[Put]]内部方法。

      10. 使用upperP、lowerValue和true作为参数调用O的[[Put]]内部方法。
      11. 否则,如果lowerExists为false且upperExists为true,则
      12. 使用lowerP、upperValue和true作为参数调用O的[[Put]]内部方法。
      13. 使用upperP和true作为参数调用O的[[Delete]]内部方法。
      14. 否则,如果lowerExists为true且upperExists为false,则
      15. 使用lowerP和true作为参数调用O的[[Delete]]内部方法。
      16. 使用upperP、lowerValue和true作为参数调用O的[[Put]]内部方法。
      17. 否则,lowerExists和upperExists都为false
      18. 无需采取任何措施。
      19. 将lower增加1。
    6. 返回O。

3
实际算法与您指定的几乎相似。只需将您的for循环更改为仅迭代到a.length/2,它就类似于Array.reverse所做的操作。出于简单起见,我在此跳过内部细节。因此,它将是:
for(var i = 0; i < a.length/2; i++) {
  var holder = a[i];
  a[i] = a[a.length - 1 - i];
  a[a.length - 1 - i] = holder;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接