Array 可能跟你想的不一樣(上)

osk2
6 min readNov 4, 2019
Photo by Caspar Camille Rubin on Unsplash

前陣子在 JavaScript 群組看到一個很有意思的問題:

const ary = [undefined, undefined, undefined];ary.forEach(v => {
console.log(v);
});
// 印出三次 undefined
const ary2 = new Array(3);
ary2.forEach(v => {
console.log(v);
});
// 這裡卻什麼都沒印出來

這問題可以拆成兩部分

  1. new Array() 建立的到底是什麼?跟 [] 不一樣嗎?
  2. 為何 new Array(3) 執行 forEach() 不會印出三次 undefined?

礙於篇幅(對,我知道太長你們會直接 End),上集只會專注在解釋第一點,forEach() 的部分就留到下集吧 👇

[undefined, undefined, undefined] 跟 new Array(3) 究竟有什麼差別?

陣列的建立

一般我們都會使用 [] 來建立陣列,也就是傳說中的 Array Literal Notation,但這跟 new Array() 有什麼不同之處嗎?

要解釋這個問題,我們得先了解 new Array() 是如何建立陣列的。先讓我們在 console 裡試試:

咦?竟然是 empty×3

咦?empty 代表什麼?跟 undefined 又有什麼不同?

註:這裡以 Google Chrome 為例,其他瀏覽器不一定會顯示為 empty

根據我們犀利的觀察,用 [] 建立的陣列確實有三個 undefined,new Array() 卻沒有,那兩者的差異是什麼呢?

我們知道 JavaScript 中除了原始型態(primitive type),其餘就是物件

既然陣列也是物件的一種,那我們試著把物件屬性印出來看看:

Object.getOwnPropertyNames([undefined, undefined, undefined]);
// ["0", "1", "2", "length"]
Object.getOwnPropertyNames(new Array(3));
// ["length"]

很明顯的,用 new Array() 建立的陣列只有 length 屬性,陣列中沒有任何數值存在

到這裡真相已經大白了,原來 new Array(3) 會建立一個只有 length 屬性的陣列

如果我們要用 Array Literal Notation 建立一個像 new Array(3) 的陣列,這樣做才是對的

new Array(3) // [empty × 3]
[,,,] // [empty × 3]

也因此 [undefined, undefined, undefined] 和 new Array(3) 根本是不同的東西呀

new Array() 的坑

雖然 new Array() 表面上看起來沒這麼糟,但其實還是有兩個缺點:

  1. 對各種傳入參數的處理行為不一致
  2. 比起 [] 多打了很多字

關於傳入參數的處理行為,根據 MDN 的說明,new Array() 可以接受無限多個參數

節錄 MDN 對 Array 的說明

如果傳入的是整數 N,且只有一個參數時,那就會建立一個 length 為 N 的空陣列。如果 N 為負數或非整數則會噴 RangeError

若是傳入的是多個整數,或其他類型的參數則會視為陣列值

直接來看個範例:

new Array('a')     // ["a"]
new Array(3) // [empty×3]
new Array(1, 2, 3) // [1 ,2, 3]
new Array(-1)
new Array(5.6)
// 上面這兩個都會導致 RangeError 錯誤

要 new Array() 何用?

看到這裡你心裡一定覺得 new Array() 這麼沒用,到底哪裡才派得上用場?

直接說答案

  1. 用於建立未知長度的陣列
  2. 某些小技巧蠻挺實用的

new Array() 其中一個不可取代的優點就是可以將變數作為參數傳入,因此我們就能建立未知長度的陣列了

const arrayLength = 10;new Array(arrayLength);

更新:

經過 JavaScript.tw 社員糾正我才知道上面說不可取代是錯的,詳見下圖

[] 也能預先設定 length

其他就是一些較不常用的小技巧,像是:

建立九個空格的字串

new Array(10).join(' ');

至於為什麼會是九格空格就讓你自己去查 ECMAScript 定義,或是看下集揭曉囉

或是建立一個填滿 5566 的陣列

new Array(3).fill('5566'); // ["5566", "5566", "5566"]

References

--

--