Array.prototype.slice.call(arguments) 到底作了什麼?

Array.prototype.slice.call(arguments) 到底作了什麼?

如題,在一些代碼中咱們常常會看到Array.prototype.slice.call(arguments) 或者[].slice.call(arguments)這段代碼,那這段代碼到底作了什麼呢?咱們就來探尋一下javascript

問題

首先來看一段代碼:java

function foo() {
	console.log(arguments)
	console.log(Array.prototype.slice.call(arguments))
}
foo(1,2,3)
複製代碼

在這個 foo 函數中咱們打印了 arguments 以及咱們常常看到的這段代碼Array.prototype.slice.call(arguments),那它們的結果確定你們都知道:es6

foo(1,2,3); 
// {0:1,1:2,2:3,length:3}
// [1,2,3]
複製代碼

大概是這樣的,並且咱們也知道arguments是一個array-like(類數組)對象,具體解釋能夠在MDN查看 ,那爲何通過了上述代碼以後就變成了真正的數組了呢?數組

具體解釋

咱們首先來明確一個事情,就是當你經過app

object.method()
複製代碼

來使用一個方法的時候,object自動成爲當前方法methodthis值,因此當像以下代碼那樣使用slice()方法的時候:函數

[1,2,3].slice()
複製代碼

[1,2,3]自動變成了slice()方法的this.這個是程序定義的,咱們若是想要修改,就須要使用 call 或者apply或者bind(他們之間的區別請看todo),這裏咱們使用 call來演示:ui

[1,2,3].slice.call([2,3,4]) //[2,3,4]
// 這樣寫是無心義的只是做爲call的展現
複製代碼

那麼回到問題上來,咱們知道arguments是個類數組對象了,若是將它做爲 slice()this值,程序會如何處理呢?
在這裏,slice 方法會認爲類數組對象已經知足它自身運行的須要(有length屬性,有數字做爲key的鍵值對),因此 slice方法會正常運行,而後獲得的結果就是返回一個真正的數組對象。this

引伸

若是咱們將 arguments 改成其餘的值,那麼會發生什麼呢?spa

Array.prototype.slice.call(123);    // []
Array.prototype.slice.call("123");    // ["1", "2", "3"]
Array.prototype.slice.call(true);   // []
Array.prototype.slice.call(null);   // error
Array.prototype.slice.call(undefined);  // error 
Array.prototype.slice.call({foo:"foo",bar:"bar",length:2});     // [empty × 2]
複製代碼

那除了這樣的方式將一個其餘類型的值轉化爲數組還有沒有其餘簡便的辦法呢?(在函數中)
咱們就可使用 es6 中的 ...rest參數了:prototype

function bar(...rest) {
	console.log(rest)
}
bar()   // []
bar(1,2,3)  //[1,2,3]
// 下面的兩種方式也是可行的
function baz() {
	console.log(Array.from(arguments))
	console.log([...arguments])
}
baz(3,4,5)
複製代碼

推薦在之後的函數中使用 ...rest參數來替換 arguments局部參數。

總結

Array.prototype.slice.call(arguments)可使一些類數組對象轉換爲對象,從而使用數組的方法來解決一些問題。

相關文章
相關標籤/搜索