你知道[ ].slice.call()的原理嗎?

一隻羊_發表於2019-03-09

在ES6以前,我們將一個偽陣列轉換為真正陣列通常情況下都是使用[ ].slice.call()方法,那麼你知道這裡面的實現原理嗎?
補充:ES6的方法為 Array.from()

首先,我們先來複習一下slice()方法:

slice(start,end)接受兩個引數,startend是將一個陣列從start項開始擷取到end項但不包含end

其次,我們再來看一下call():

call(thisArg,arg1, arg2, ...)thisArg代表當前函式執行時this的指向,args為函式的引數(this的指向問題不在這裡過多補充,還不清楚的同學可以自行搜尋)

最後,我們再回憶一下什麼是偽陣列:
偽陣列有一個明確的標識,length屬性,並且是以索引的方式進行儲存:

let array = { '0': 'a', '1': 'b', '2': 'c', length: 3 }
如上,一個非常典型的偽陣列。

補充:我們都知道slice是js陣列的原生方法,所以在使用時還有一種寫法就是Array.prototype.slice.call()

那麼[].sliceArray.prototype.slice有什麼區別呢?其實通常情況下兩者並無區別,這個可以通過列印[].slice === Array.prototype.slice來佐證。

複習完了基礎理論,我們現在就來捋一捋這兩者之間是如何實現將一個偽陣列轉化成真正陣列的。
舉個例子:

function test({
    return  [].slice.call(arguments)
}
var list = test(456// [4,5,6]
複製程式碼

在上面的例子中我們通過call()將[].slice中的this指向了arguments,使其擁有了slice方法。slice()如果不傳參則是從第0項開始擷取到length-1項並返回擷取後的陣列[4,5,6]上面其實就是省略了call()的第二個引數,你可以把它看作為[].slice.call(arguments,0)

綜上,其實現的主要原理就是利用改變this的指向來實現繼承。

以上就是我所理解的實現原理,如有誤歡迎指正,必定虛心接受。

相關文章