背景
《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]