淺析"對arguments物件使用Array.prototype.slice()可以將其轉化為陣列"

深藍一人發表於2017-11-21

背景

《Javascript高階程式設計(第3版)》的250頁有一句話叫“對arguments物件使用Array.prototype.slice()可以將其轉化為陣列”,為什麼這麼說?

arguments

Js中的每一個函式(箭頭函式除外)自動獲得兩個變數this和arguments。因此隨便定義一個非箭頭函式,可以列印出它的auguments;

> function add (a, b) { return arguments;}
> var arg = add (1, 2);
> arg  // 列印arg複製程式碼

列印結果

arg並不是一個陣列,但是可以通過arg[0],arg[1]及arg.length來獲取引數的一些屬性。可以通過Array.prototype.slice()來將其轉化為一個陣列

上圖中可以看出以下兩點:

1.Array.prototype.slice()返回一個新陣列
2.Array.prototype.slice()並不會影響其引數

Array.prototype.slice()

Array.prototype.slice是怎麼實現返回一個新陣列的呢?網上也有一些通過看原始碼來解析其原理的文章,例如 www.cnblogs.com/henryli/p/3… ,但是作為一個前端這個理解起來有一定的困難,我的建議是檢視loadash對slice的實現來理解一下其原理。
文件:lodash.think2011.net/slice
原始碼:github.com/lodash/loda…

_.slice(array, [start=0], [end=array.length])
建立一個裁剪後的陣列,從 start 到 end 的位置,但不包括 end 本身的位置。

/**
 * Creates a slice of `array` from `start` up to, but not including, `end`.
 *
 * **Note:** This method is used instead of
 * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
 * returned.
 *
 * @since 3.0.0
 * @category Array
 * @param {Array} array The array to slice.
 * @param {number} [start=0] The start position.
 * @param {number} [end=array.length] The end position.
 * @returns {Array} Returns the slice of `array`.
 */
function slice(array, start, end) {
  let length = array == null ? 0 : array.length
  if (!length) {
    return []
  }
  start = start == null ? 0 : start
  end = end === undefined ? length : end

  if (start < 0) {
    start = -start > length ? 0 : (length + start)
  }
  end = end > length ? length : end
  if (end < 0) {
    end += length
  }
  length = start > end ? 0 : ((end - start) >>> 0)
  start >>>= 0

  let index = -1
  const result = new Array(length)
  while (++index < length) {
    result[index] = array[index + start]
  }
  return result
}複製程式碼

因此當我們使用Array.prototype.slice.call(arg, 0)時,實際上返回了一個新的陣列result,該陣列的長度等於arg.length,其元素包含從0到arg.length的所有元素,即arg[0],arg[1]

相關文章