新增的靜態函式
Array.of
函式型別:
//接收任意數量、任意型別的引數,返回這些引數按照傳入順序組成的陣列 (...args?:any[])=>any[];
Array.of
用於建立一個具有可變數量引數的新的陣列例項。它和通過Array
建構函式建立陣列的不同之處在於,當使用new Array
的方式建立陣列時,如果只傳入了一個整數引數a
,則會建立一個長度為a
的陣列,每個元素都是空位(指empty
,而不是undefined
),而Array.of
則會建立返回[ a ]
。console.log(Array(3)); //[ <3 empty items> ] console.log(Array.of(3)); // [ 3 ]
當我們需要根據傳入的引數來建立陣列時,如果使用的
Array
建構函式,而且沒有特殊處理引數只有一個整數的情況,就會出現意料之外的情況。這種並非邏輯上的、細節性的問題,在修復時,往往我們也是最難以意識到的一類問題。Array.from
函式型別:
/** * @author: forceddd * @desc: 根據傳入的一個偽陣列或可迭代物件建立一個新的、淺拷貝的陣列例項 * @param {ArrayLike<any>|Iterable<any>} arrayLike 傳入的資料來源 * @param {MapFn} mapFn 可選的對映函式,與Array.map用途相同 * @param {any} thisArg 可選的this物件,對映函式mapFn中的this會指向該引數 * @return {any[]} 新建立的陣列 */ (arrayLike: ArrayLike<any> | Iterable<any>, mapFn?: MapFn, thisArg?: any) => any[]; /** * @author: forceddd * @desc: 對映回撥 * @param {any} value 陣列中的元素 * @param {number} index 元素的在陣列中的下標 * @return {any} 對映返回的值 */ type MapFn = (value: any, index: number) => any;
Array.from
是根據傳入的一個偽陣列或可迭代物件建立一個新的、淺拷貝的陣列例項。與
Array.of
不同,Array.of
是直接將引數作為返回值陣列中的元素,而Array.from
會根據傳入的引數來產生返回值陣列:當傳入偽陣列時,偽陣列的
length
會作為返回值陣列的length
,偽陣列的元素會作為返回值陣列的元素。//傳入了一個偽陣列 console.log(Array.from({ 0: '第一項元素', length: 2 }));//[ '第一項元素', undefined ] // tag屬性不能轉換成陣列下標,被過濾掉了 console.log(Array.from({ 0: '第一項元素', length: 2, tag: '一個字串key' }));//[ '第一項元素', undefined ] //傳入的是一個普通物件,既不是偽陣列,也不是一個iterable物件,返回一個空陣列 console.log(Array.from({ 0: '第一項元素', tag: '一個字串key' }));//[]
當傳入一個
iterable
物件引數時,比如Array
,Set
等,會對引數進行迭代,並將迭代得到的值作為返回值陣列中的元素。console.log(Array.from([1, , 3])); //[ 1, undefined, 3 ] console.log(Array.from(new Set([1, , 3]))); //[ 1, undefined, 3 ] //傳入了一個對映函式 console.log(Array.from([1, 2, 3], (item) => 2 * item)); //[ 2, 4, 6 ] const obj = { value: 0, //自定義 [Symbol.iterator] ,是該物件成為iterable物件,執行得到的迭代器是它自身 [Symbol.iterator]() { return this; }, //value > 3 後,設定迭代狀態為true,結束迭代 next() { this.value++; return { value: this.value, done: this.value > 3, }; }, }; //傳入一個自定義的iterable console.log(Array.from(obj));//[ 1, 2, 3 ]
需要注意的是,
Array.from
不會產生空位(empty
),如果傳入的引數中,該位置的元素是空位(empty
),會使用undefined
作為結果。當我們需要將一個偽陣列轉為真正的陣列,以便使用陣列的
map
等方法時——比如進行dom操作,相較於使用[].slice.call(arrayLike)
來說(這種方法有可能產生空位(empty
)元素),使用Array.from
無疑是一個更優雅也更簡潔的方式。為什麼要避免陣列中的空位元素?
在處理陣列的函式中,不同的函式對待空位元素的方式是不同的,有些函式會忽略空位元素,比如
map
函式,而有些則不會忽略,比如Array.from
,這就很有可能會產生一些莫名其妙的問題。假如我們需要通過變數
count
統計一個陣列的length
,這可以讓我們很明顯的看到空位元素的問題所在。當存在空位元素時:
const empty = [1, , 3]; let count1 = 0; let count2 = 0; empty.map(() => count1++); Array.from(empty, () => count2++); //由於map函式忽略了空位元素,所以傳入的回撥只執行了兩次,count1的值為2 console.log({ count1, count2 }); //{ count1: 2, count2: 3 }
當不存在空位元素時:
const normal = [1, undefined, 3]; let count1 = 0; let count2 = 0; normal.map(() => count1++); normal.forEach(() => count2++); console.log({ count1, count2 }); //{ count1: 3, count2: 3 }