展開
先宣告兩個陣列
1 | let arr1 = ['A', 'B', 'C'] |
合併陣列
1 | // ES5 |
複製陣列
1 | // ES5 |
陣列開頭插入陣列(物件)
1 | // ES5 |
原理
1 | console.log(...arr1) // A B C |
單純印出 ...arr1
會出現陣列內的內容,我們可以理解 ... 這個運算子
的作用是將它後方的陣列值一個個取出來,然後再 push
回去。
類陣列 (array like)
定義:擁有一個 length 屬性 和 若干索引屬性 的
物件
。
手動創造一個類陣列
以物件實體語法創造一個物件,其成員的屬性皆為索引(數字),並賦予額外 length 屬性。
1 | var arrayLike = { |
操作
1 | // 讀寫 |
Arguments
Arguments 是當函數的執行環境被創造時與 環境變數、this、外部環境一起被 JavaScript 引擎創造出來的物件。他也是一個類陣列,而裡面的屬性是所有被傳入該函數的參數。
1 | function foo() { |
輸出:
可以看到輸出結果產生了類陣列的物件,而__proto__
內的方法皆是物件的原生方法。
如果嘗試用 arguments
使用陣列的 push
方法,會跳出錯誤。因為 arguments是物件不是陣列。
1 | function foo() { |
利用展開將類陣列轉換成陣列,如此也可以順利取用陣列的方法。
1 | function foo() { |
結果:
querySelectorAll()
1 | <ul> |
1 | let doms = document.querySelectorAll('li') |
可以發現用 querySelectorAll
所產生的變數doms,看起來好像是個陣列,仔細看發現紅框上面寫的是 NodeList
而不是陣列會顯示的 Array
,這是一個典型的類陣列例子。
進一步做驗證,打開 __proto__
看看內部的原生方法,可以很快的發現和我們所知的陣列方法是有出入的,真正的陣列方法並沒有這麼少。
而陣列方法 concat
在 doms.__proto__
也找不到,如果試著對 doms 使用這個方法的話,不意外的跳錯了。
如果類陣列就是很任性的想使用陣列的方法,可以嗎?
假設變數 arrayLike
是一個類陣列
ES6
先轉為陣列,之後可以合理使用陣列方法了。
1 | //1 |
ES5
使用call
、apply
、bind
,呼叫陣列的方法。
1 | //1 |
輸出:
看看它的 __proto__
,可以發現他已經有所有陣列該有的原生方法了,現在就可以直接取用這些方法,不需要再使用call
、apply
、bind
,也可以證明它已經變成一個真正的陣列了。
其餘
在克服JS奇怪部分 4-39最後提到的Speard,就是指展開與其餘,當時影片錄製時,ES6功能還不夠完整,講師提到未來這個功能如果完善了,將可以取代 Arguments
,下面來看看如何使用吧。
1 | function foo(...people) { // 自定義陣列名稱 (裡面包含傳入的參數) |
結果可以發現不同於 Arguments
,其餘參數所創造的陣列是純粹的陣列而不是偽陣列:
另外如果還有其他參數並不想加入其餘參數陣列當中,我們可以
1 | function foo(area, road, ...people) { // 自定義陣列名稱 (裡面包含傳入的參數) |
結果可以發現若有額外設計參數,一樣會一一對應並帶入,而剩餘的參數將直接被放入其餘參數的陣列當中。
注意:其餘參數一定要在最後,且只能有一個