iT邦幫忙

2022 iThome 鐵人賽

DAY 8
0
Modern Web

前端蛇行撞牆記系列 第 8

Day8 前端蛇行撞牆記 - 不用宣告一個空陣列也可以創建陣列的方法

  • 分享至 

  • xImage
  •  

前言

其實這不是什麼高深的學問,不過的確是一陣子我就會忘記的方法,所以想要為自己寫個筆記。

為什麼會需要這個方法?當時我在學習JS一陣子,突然有學長說在建立一個新array時不要用const a = []這個方法,還有只要一個function裡面有先宣告一個新陣列,最後再return 這個array,幾乎都有陣列方法去達到這件事。

於是我開始找方法來生出一個陣列並且已經把東西放好了。


方法一:Array(number).fill(0).map()

const a = Array(3).fill(0).map((item, index) => index)

console.log(a) 
// [ 0, 1, 2 ]

利用建構式函示來創造出新的陣列(這裡有沒有new都沒關係),在Array()裡面可以放Array(1,2,3)會自動生成[1,2,3],可是如果放的是單個數字,他就會生成裡面有三個空物件的陣列。

像是這樣:

const a = Array(3)

console.log(a) 
// [ <3 empty items> ]

這個[ <3 empty items> ]有點難搞,雖然有空的東西在裡面,但他並沒有佔一格位子,不過是可以用.fill(0)來把裡面的空間都站滿,然後再把他們全部map()去放入其他的值進去。

為什麼要這樣呢?直接const a = Array(3).fill(1,2,3)不就好了?這是因為fill()有嚴重的pass by reference的問題,我們來試試看這個例子:

  • 想要在陣列裡面每一格放空物件,MDN的範例:
// A single object, referenced by each slot of the array:
const arr = Array(3).fill({}); // [{}, {}, {}]
arr[0].hi = "hi"; 

console.log(arr)
// [{ hi: "hi" }, { hi: "hi" }, { hi: "hi" }]

我只是想要改index 0,結果全部都改到了!
所以直接把空物件放進去的話,fill({})裡面的空物件都是指向同一個reference物件,所以當只要改陣列其中一個index的時候就會全部都改成一樣的!!

如果使用我的作法,就不會參考到同一個reference了。

const arr = Array(3).fill(0).map(() => {
    return {};
  });

arr[0] = { name: "jade" };
console.log(arr);
// [ { name: 'jade' }, {}, {} ]

方法二:Array.apply()

這個方法是我在《you don’t know JS》看到的。
我想那個時候可能還沒有fill(),作者說以前使用new Array(3)的方式好像是產生[, , ,]只有逗號這樣的狀況,而且這樣其實是四個位置啊,所以也是超不推這個作法。

  • 這是他當時建議可以試的方法:
const a = Array.apply(null, { length: 3 }).map((item, index) => index);

console.log(a);
// [ 0, 1, 2 ]

雖然apply是Function.prototype.apply()的但是陣列也可以使用,apply第一個參數綁定的是this, 第二個參數則是argsArray,可以提供放一個類陣列進去。

然而在這裡第二個參數放的是{ length: 3 }就是類陣列裡面定義長度的意思,就可以直接定義這個陣列的長度。

  • 寫成這樣也是同等意思:
const a = Array.apply(null, Array(3)).map((item, index) => index);

console.log(a);
// [ 0, 1, 2 ]

我是覺得變成這樣比較好讀。

方法三:Array.from()

跟方法二有點像,也是利用類陣列的物件特性去創造的。

  • 複習一下Array.from()的用法:
Array.from(arrayLike[, mapFn[, thisArg]])
  • 範例:
const a = Array.from({ length: 3 }, (element, index) => {
  return index;
});

console.log(a);
// [ 0, 1, 2 ]

這個方法也滿清楚的,大家應該都知道Array.from()是拿來把類陣列變成陣列的,所以如果是直接使用Array.from(),第一個參數的{ length: 3 }就會滿好理解的。

而第二個參數則是像map一樣會遍歷陣列裡面每一個值。

總結:

直接懶人包放上來,全部的console.log(a)都會是[0, 1, 2]

  • const a = Array(3).fill(0).map((item, index) => index)
  • const a = Array.apply(null, { length: 3 }).map((item, index) => index);
  • const a = Array.from({ length: 3 }, (element, index) => { return index; });

以上。

如果還有其他方法請報我知~
有錯誤的地方也要讓我知道喔~

明天見拉~


參考資料:你所不知道的JS
在 JavaScript 中建立特定長度的陣列
What is Array.apply actually doing


上一篇
Day7 前端蛇行撞牆記 - 親愛的 forEach()
下一篇
Day9 前端蛇行撞牆記 - 淺入了解array-like
系列文
前端蛇行撞牆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
Chris
iT邦新手 4 級 ‧ 2022-09-29 23:55:18

Array(1, 2, 3) // [1, 2, 3]

0
ayugioh2003
iT邦新手 2 級 ‧ 2022-09-30 11:25:12

看起來是要建立連續陣列
我最近常用的方式是這樣 ~

[...Array(3)].map((v, i) => i)
jadddxx iT邦新手 5 級 ‧ 2022-10-11 10:59:26 檢舉

這個也好快,直接使用展開運算子~謝謝!

我要留言

立即登入留言