ES6新增API:Array篇(一)

forceddd發表於2021-11-25

新增的靜態函式

  1. 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建構函式,而且沒有特殊處理引數只有一個整數的情況,就會出現意料之外的情況。這種並非邏輯上的、細節性的問題,在修復時,往往我們也是最難以意識到的一類問題。

  2. 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物件引數時,比如ArraySet等,會對引數進行迭代,並將迭代得到的值作為返回值陣列中的元素。

    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無疑是一個更優雅也更簡潔的方式。

  3. 為什麼要避免陣列中的空位元素?

    在處理陣列的函式中,不同的函式對待空位元素的方式是不同的,有些函式會忽略空位元素,比如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 }

相關文章