ECMA Script 6_數組的擴展_擴展運算符

1. 擴展運算符node

內部調用的是數據結構的 Iterator 接口,數組

所以只要具備 Iterator 接口的對象,均可以使用擴展運算符 ...數據結構

如 map,,,,app

[...arr]函數

擴展運算符(spread)是三個點(...)this

將一個數組轉爲用逗號分隔的參數序列spa

  • console.log(...[1, 2, 3]);    // 1 2 3
     console.log(1, ...[2, 3, 4], 5);    // 1 2 3 4 5
     [...document.querySelectorAll('div')];    // [<div>, <div>, <div>]
  • 主要用於函數調用
  • function push(array, ...items) { array.push(...items); }; function add(x, y) { return x + y; }; const numbers = [4, 38]; add(...numbers); // 42
  • 擴展運算符後面還能夠放置表達式
  • const arr = [ ...(x > 0 ? ['a'] : []), 'b', ];
  • 若是擴展運算符後面是一個空數組,則不產生任何效果
  • [...[], 1];    // [1]
  • 再也不須要apply方法,將數組轉爲函數的參數了
  • function f(x, y, z) { // ...
    } f.apply(null, [0, 1, 2]);    // ES5 的寫法
     f(...[0, 1, 2]); // ES6的寫法
  • Math.max.apply(null, [14, 3, 77]);    // ES5 的寫法
     Math.max(...[14, 3, 77]); // ES6 的寫法
    
    // 等同於 Math.max(14, 3, 77);;   
  • var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; Array.prototype.push.apply(arr1, arr2); // ES5 的寫法
     arr1.push(...arr2); // ES6 的寫法

2. 複製數組 ...prototype

ES5 只能用變通方法來複制數組code

  • const a1 = [1, 2]; const a2 = a1.concat(); a2[0] = 2; a1 // [1, 2]
  • ES6 使用 ...複製數組        但仍是淺拷貝
  • const a1 = [1, 2]; const a2 = [...a1]; // 寫法一  const [...a2] = a1;    // 寫法二

若是將擴展運算符用於數組賦值,只能放在參數的最後一位,不然會報錯對象

  • 擴展運算符還能夠將字符串轉爲真正的數組
  • [...'hello'];    // [ "h", "e", "l", "l", "o" ]

    好處,那就是可以正確識別四個字節的 Unicode 字符。

  • 'x\uD83D\uDE80y'.length     // 4
    [...'x\uD83D\uDE80y'].length     // 3 正確返回字符串長度的函數

正確返回字符串長度

  • function length(str) { return [...str].length; }; length('x\uD83D\uDE80y');    // 3

3. Array.from()

Array.from() 用於將如下兩類對象轉爲真正的數組

  • 相似數組的對象(array-like object)
  • 遍歷(iterable)的對象(包括 ES6 新增的數據結構 Set 和 Map)

任何有 length 屬性的對象,均可以經過 Array.from() 轉爲數組,而彌補 擴展運算符 ... 就沒法轉換

由於 擴展運算符... 只對有 Iterator 接口的對象, 轉爲真正的數組

  • 實例
  • let arrayLike = { '0': 'a', '1': 'b', '2': 'c', length: 3 }; var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c'] // ES5的寫法
     let arr2 = Array.from(arrayLike); // ['a', 'b', 'c'] // ES6的寫法
  • querySelectorAll() 返回的是一個 NodeList 對象。它不是數組,而是一個相似數組的對象。

這時,擴展運算符能夠將其轉爲真正的數組,緣由就在於 NodeList 對象實現了 Iterator

  • let nodeList = document.querySelectorAll('div'); 
    let array
    = [...nodeList];

    let arr = Array.from(nodeList);
  • 字符串轉數組,Set 對象 轉 數組
  • Array.from('hello');    // ['h', 'e', 'l', 'l', 'o']
     let namesSet = new Set(['a', 'b']); Array.from(namesSet); // ['a', 'b']

4. Array.from() 還能夠接受第二個參數,做用相似於數組的map方法,用來對每一個元素進行處理,將處理後的值放入返回的數組

  • Array.from(arrayLike, x => x * x); // 等同於
    Array.from(arrayLike).map(x => x * x); Array.from([1, 2, 3], (x) => x * x);    // [1, 4, 9]
  • 將數組中 布爾值爲 false 的成員轉爲 0
  • Array.from([1, , 2, , 3], (n) => n || 0);    // [1, 0, 2, 0, 3]
  • 返回各類數據的類型
  • function typesOf () { return Array.from(arguments, value => typeof value) }; typesOf(null, [], NaN);    // ['object', 'object', 'number']
  • 完美計算 length
  • function countSymbols(string) { return Array.from(string).length; }:

    由於它能正確處理各類 Unicode 字符,能夠避免 JavaScript 將大於\uFFFF的 Unicode 字符,算做兩個字符的 bug

  • 傳入 Array.from() 第三個參數,用來綁定 this

4. Array.of

將一組值,轉換爲數組

  • Array.of(3, 11, 8);    // [3,11,8]
    Array.of(3);    // [3]
    Array.of(3).length;    // 1
  • 基本上能夠用來替代 Array() 或 new Array(),而且 不存在 因爲 參數不一樣 致使重載。它的行爲很是統一
  • Array.of();    // []
    Array.of(undefined);    // [undefined]
    Array.of(1);    // [1]
    Array.of(1, 2);    // [1, 2]

5. 數組實例的 Array.prototype.copyWithin(target, start = 0, end = this.length)

數組實例的 arr.copyWithin()

在當前數組內部,將指定位置的成員複製到其餘位置(會覆蓋原有成員),而後返回當前數組

也就是說,使用這個方法,會修改當前數組。

target(必需)        從 target 開始替換數據。若是爲負值,表示倒數。
start(可選)       從 start 開始讀取數據,默認爲 0。若是爲負值,表示倒數。
end(可選)       到 end 前中止讀取數據,默認等於數組長度。若是爲負值,表示倒數。

這三個參數都應該是數值,若是不是,會自動轉爲數值

  • [1, 2, 3, 4, 5].copyWithin(0, 3);    // [4, 5, 3, 4, 5]
  • // 將3號位複製到0號位
    [1, 2, 3, 4, 5].copyWithin(0, 3, 4);    // [4, 2, 3, 4, 5]
    
    
    // -2至關於3號位,-1至關於4號位
    [1, 2, 3, 4, 5].copyWithin(0, -2, -1);    // [4, 2, 3, 4, 5]
    
    
    // 將3號位複製到0號位
    [].copyWithin.call({length: 5, 3: 1}, 0, 3);    // {0: 1, 3: 1, length: 5}
    
    
    // 將2號位到數組結束,複製到0號位
    let i32a = new Int32Array([1, 2, 3, 4, 5]);
    i32a.copyWithin(0, 2);    // Int32Array [3, 4, 5, 4, 5]
    
    
    // 對於沒有部署 TypedArray 的 copyWithin 方法的平臺    須要採用下面的寫法
    [].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4);;    // Int32Array [4, 2, 3, 4, 5]

6. arr.find()

找出第一個符合條件的數組成員

它的參數是一個回調函數,全部數組成員依次執行該回調函數,直到找出第一個返回值爲 true 的成員,而後返回該成員

若是沒有符合條件的成員,則返回 undefine

  • [1, 4, -5, 10].find((n) => n < 0);    // -5
  • [1, 5, 10, 15].find(function(ele, index, arr) {
        return ele > 9;
    });    // 10

 

7. arr.findIndex()

返回第一個符合條件的數組成員的位置

若是全部成員都不符合條件,則返回-1

  • [1, 5, 10, 15].findIndex(function(value, index, arr) {
        return value > 9;
    });    // 2
  • arr.find() arr.findIndex() 均可以接受第二個參數,用來綁定回調函數的this對象
  • let person = {name: 'John', age: 20};
    [10, 12, 26, 15].find(function(ele){
        return v > this.age;
    }, person);    // 26
  • arr.find() 和 arr.findIndex() 均可以發現NaN,彌補了數組的 indexOf 方法的不足

內部其實藉助 Object.is 發現了 NaN

8. arr.fill() 

使用給定值填充一個數組

第一個參數: 給定值

第二個參數: 填充起始位置

第三個參數: 填充結束位置        end 不會被填充

  • ['a', 'b', 'c'].fill(7);    // [7, 7, 7]
    
    new Array(3).fill(7);    // [7, 7, 7]
    
    ['a', 'b', 'c'].fill(7, 1, 2);    // ['a', 7, 'c']
  • 用於空數組的初始化很是方便。數組中已有的元素,會被所有抹去
  • 若是填充的類型爲對象,那麼被賦值的是同一個內存地址的對象,而不是深拷貝對象
  • let arr = new Array(3).fill({name: "Mike"});
    arr[0].name = "Ben";
    console.log(arr);    // [{name: "Ben"}, {name: "Ben"}, {name: "Ben"}]
    
    let arr = new Array(3).fill([]);
    arr[0].push(5);
    console.log(arr);    // [[5], [5], [5]]

9. ES6 遍歷數組新方法

都返回一個遍歷器對象,能夠用 for...of 循環進行遍歷

arr.entries()        是對鍵值對的遍歷

arr.keys()        是對鍵名的遍歷

arr.values()        是對鍵值的遍歷

arr.entries()

  • for (let [index, elem] of ['a', 'b'].entries()) {
        console.log(index, elem);
    };
    // 0 "a"
    // 1 "b"

arr.keys()

  • for (let index of ['a', 'b'].keys()) {
        console.log(index);
    };
    // 0
    // 1

arr.values()

  • for (let ele of ['a', 'b'].values()) {
        console.log(ele);
    };
    // 'a'
    // 'b'
  • 不使用 for...of 循環,能夠手動調用遍歷器對象的 next() 方法,進行遍歷
  • let letter = ['a', 'b', 'c'];
    let entries = letter.entries();
    console.log(entries.next().value);    // [0, 'a']
    console.log(entries.next().value);    // [1, 'b']
    console.log(entries.next().value);    // [2, 'c']

10. arr.includes()

返回一個布爾值,表示某個數組是否包含 給定值,與字符串的 includes 方法相似

第一個參數: 給定值

第二個參數: 表示搜索的起始位置,默認爲 0

若是第二個參數爲負數,則表示倒數的位置,

若是這時它大於數組長度(好比第二個參數爲-4,但數組長度爲3),則會重置爲從 0 開始

  • [1, 2, 3].includes(2);     // true
    [1, 2, 3].includes(4);     // false
    [1, 2, NaN].includes(NaN);    // true
  • Map 和 Set 數據結構有一個has方法,須要注意與includes區分
  • Map 結構的has方法,是用來查找鍵名的

Map.prototype.has(key)

WeakMap.prototype.has(key)

Reflect.has(target, propertyKey)

  • Set 結構的has方法,是用來查找值的

Set.prototype.has(value)

WeakSet.prototype.has(value)

11. arr.flat()

將嵌套的數組 "拉平",變成一維的數組。該方法返回一個新數組,對原數據沒有影響

  • [1, 2, [3, 4]].flat();    // [1, 2, 3, 4]

arr. flat() 只有一個參數,指定「拉平」 多少層,默認爲1

傳遞一個整數,表示想要拉平的層數,

若是無論有多少層嵌套,都要轉成一維數組,能夠用 Infinity 關鍵字做爲參數

  • [1, 2, [3, [4, 5]]].flat();    // [1, 2, 3, [4, 5]]
    
    [1, 2, [3, [4, 5]]].flat(2);    // [1, 2, 3, 4, 5]

    [1, [2, [3]]].flat(Infinity);    // [1, 2, 3]

  • 若是原數組有空位,arr.flat() 處理後會去掉
  • [1, 2, , 4, 5].flat();    // [1, 2, 4, 5]

12. arr.flatMap()

對原數組的每一個成員執行一個函數(至關於執行Array.prototype.map()),

而後對返回值組成的數組 arr 執行 arr.flat()方法。

該方法返回一個新數組,不改變原數組

參數:

第一個參數: 回調函數

第二個參數: 綁定 this 指向

  • // 至關於 [[[2]], [[4]], [[6]], [[8]]].flat()
    [1, 2, 3, 4].flatMap(x => [[x * 2]]);    // [[2], [4], [6], [8]]

13. 數組的空位

數組的某一個位置沒有任何值。好比,Array 構造函數返回的數組都是空位

ES5 對空位的處理,已經很不一致了,大多數狀況下會忽略空位

ES6 則是明確將空位轉爲 undefined,而不會忽略空位

  • Array.from(['a',,'b']);    // [ "a", undefined, "b" ]
相關文章
相關標籤/搜索