ES6入門之陣列的擴充套件

故事膠片發表於2019-05-08

ES6入門之陣列的擴充套件

1. 擴充套件運算子

...表示,將一個陣列轉為用逗號分隔的引數序列,如下:

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 add(x, y){
    return x + y
}
const n = [3, 5]
add(...n) // 8
複製程式碼
擴充套件運算子可以和正常函式結合使用,如下:
function f(a,b,c,d,e){
    console.log(a,b,c,d,e)
}
const age = [0,1]

f(-1,...age,2,...[3]) // -1 0 1 2 3
複製程式碼
擴充套件運算子後面也可以是表示式,如下:
const x = 10
const arr = [
    ...(x > 0 ? ['a'] : []), 'b',
]

arr // ['a', 'b']
複製程式碼
重要:如果擴充套件運算子後面是一個空陣列,將不會有任何效果。另外只有在函式呼叫的時候擴充套件函式在放在圓括號之內,其他的則會報錯。
替代函式的apply方法

擴充套件函式可以展開陣列,所以將不需要apply方法來將陣列轉換為函式的引數。

function f(x, y, z){
    console.log(x, y, z)
}

var a = [1,2,4]

// ES5 
f.apply(null, args)

// ES6
f(...a)


// Math.max方法

//ES5
Math.max.apply(null, [14, 3, 99])

//ES6
Math.max(...[12, 4, 55])

//等同於
Math.max(12, 4, 55)

// push方法的應用

var a = [0,1,2]
var b = [3,4,5]

//ES5
Array.prototype.push.apply(a,b) // 0,1,2,3,4,5

//ES6
a.push(...b)
複製程式碼
擴充套件運算子的應用
  1. 複製陣列

     因為陣列是複合的資料型別,直接的複製只是複製陣列在堆記憶體中的指標地址
     
     const a1 = [1,2]
     const a2 = a1
     
     a2[0] = 3
     a1 // [3,2]
    
     // ES5 通過變通方法來複制
     const a1 = [1,2]
     const a2 = a1.concat()
    
     a2[0] = 23
     a1 // [1,2]
     
     // ES6寫法
     const b1 = [1,3]
     const b2 = [...b1] or [...b2] = b1
    複製程式碼
  2. 合併陣列

     const a1 = ['b', 'c']
     const a2 = ['d']
     const a3 = ['x', 'y']
     
     // ES5中合併陣列
     a1.concat(a2, a3)
     
     // ES6中合併陣列
     [...a1, ...a2, ...a3]
    
     //以上兩種都是淺拷貝,修改原陣列和同步新陣列
    複製程式碼
  3. 與解構賦值一起使用,擴充套件只能放在最後一位,不然會報錯

     // ES5
     a = list[0], rest = list.slice(1)
    
     // ES6
     [a,...rest] = list
    
     // 其他
     const [a,...c] = [1,2,4,5,4,6] // a 1   c 2,4,5,4,6
     const [a,...c] = [] // a undefined   c []
     const [a,...c] = ['a'] // a 'a'   c []  
    複製程式碼
  4. 字串,將字串轉換為陣列

     [...'hello'] // [h,e,l,l,0]
    複製程式碼
  5. 實現了Iterator介面的物件

     任何定義了遍歷器介面物件,都可以用擴充套件運算子轉為真正的陣列
    
     let nodelist = document.querySelectorAll('div')
     let array = [...nodelist]
     // querySelectorAll 返回的是一個類陣列,通過擴充套件運算子
     將其轉換為一個真正的陣列
    複製程式碼
  6. Map 和 Set 解構,Generator函式

     擴充套件運算子呼叫的是資料解構的Iterator介面,只要有Iterator介面的
     物件,都可以使用擴充套件運算子
    
     // Map
     let map = new Map([
         [1, 'a'],
         [2, 'b'],
         [3, 'c'],
     ])
     let arr = [...map.keys()] // 1, 2, 3
     let arr = [...map.values()] // 'a', 'b', 'c'
     
     //Generator函式
     const go = function*(){
         yield 1;
         yield 2;
         yield 3;
     }
     [...go()] // [1, 2, 3]
    複製程式碼

2. Array.from()

Array.from 方法用於將兩類物件轉為真正的陣列。1、類似陣列物件 和 可遍歷的物件(包裹Set和Map),如下:

let arrLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
}

// ES5 
var a1 = [].slice.call(arrLike)

// ES6
var a2 = Array.from(arrLike)
複製程式碼

在實際中,像獲取dom後返回的Nodelist集合,以及函式內部的arguments物件就是類陣列,通過 Array.from將它們轉換為真正的陣列。

// NodeList 物件
let ps = document.querySelectorAll('p')
Array.from(ps).filter(p => {
    return p.textContent.length > 100
})

// arguments 物件
function foo(){
    var arg = Array.from(arguments)
}

// 只要部署了Iterator介面的資料解構,Array.from都能將其轉成陣列
Array.from('hello') // ['h', 'e', 'l', 'l', 'o']

let nl = new Set([1, 2])
Array.from(nl) // [1, 2]

// 如果是真陣列則返回一樣的
Array.from([1, 2, 3]) // [1, 2, 3]
複製程式碼

... 擴充套件運算子也可以將某些類陣列轉換為陣列,如arguments和NodeList集合

擁有lenght屬性的物件都可以通過Array.from轉換為陣列,而擴充套件運算子則不行。

Array.from({lenght:3}) // [undefined, undefined, undefined]
複製程式碼

對於低版本的瀏覽器,可以通過 Array.prototype.slice 方法替代

Array.from 還可以接受第二個引數如同map一樣,用來對每個元素進行操作,並將處理後的值放入返回的陣列中。

const arrlike = new Set([1,2,3])
Array.from(arrlike, x => x * x)   // =
Array.from(arrlike).map(x => x * x)   // [1, 4, 9]

//注意: 如果map中用到了this,可以傳入Array.from
的第三個引數,用來繫結this
複製程式碼

Array.from 可以將各種值轉換為真正的陣列,並且還提供map相關功能,這樣代表如果有個原始資料結構,可以先將他轉換為陣列,然後使用陣列相關的方法。

3. Array.of()

用於將一組值,轉換為陣列。主要用來彌補Array函式因為引數個數不同而導致的差異

Array.of(3,11,6) // [3, 11, 6]
Array.of(3) // [3]
Array.of(4).length // 1
複製程式碼

4. 陣列的例項 copyWithin()

將當前陣列中指定位置的元素複製到另外一個位置,並且會覆蓋那個位置的原有元素,會修改當前陣列

// 有三個引數
1. target(必須):從該位置開始替換資料,如果是負值,則倒數
2. start(可選):從該位置讀取資料,預設0,負值同上
3. end(可選):到這個位置停止讀取資料,預設等於陣列長度,負值同上

    
let p = [1,2,3,4,5,6,7]
p.copyWithin(0,5,7)
[6, 7, 3, 4, 5, 6, 7]
複製程式碼

5. 陣列例項的 find() 和 findIndex()

find 用來找出陣列中符合條件的成員,它的引數是一個回撥函式,找到一個返回值為true的返回,如果沒有則返回undefined

let s = [1,2,3,4,5,6]

s.find(x => x > 4)
// 5

find 方法的回撥函式有三個引數
    
    value // 當前值
    index // 當前的位置
    arr // 原陣列
複製程式碼

findIndex 同find方法類似,只不過都不符合返回的是 -1,而且符合是返回符合條件值的位置而不是值。

let s = [1,2,3,4,5,6]

s.find(x => x > 4)
// 4
複製程式碼

find 和 findIndex 都可以接受第二個引數

function o(p){
    return p > this.age
}

const u = {name: 'cx', age: 11}
const y = [8,11,22,2,4]

y.find(o, u) // 22  返回的值
y.findIndex(o, u) // 2  返回值的位置
複製程式碼

6. 陣列例項的 fill()

通過給定值,填充一個陣列

let sz = [1,2,3,4,5,6]

sz.fill(1) // [1,1,1,1,1,1]

sz.fill(1,0,3) 
// 接受三個引數,第一個為填充值,第二個為起始位置,第三個為截至位置

sz.fill(1,3)
// 如果省略最後一個引數,則預設從起始位置到陣列預設長度結束
複製程式碼

7. 陣列例項的 entries(), keys(), values()

三種方法主要用於遍歷陣列,可以用 for...of...進行遍歷,keys()對應鍵名,values對應鍵值,entries()對鍵值對的遍歷

let bo = ['a', 'c']

for(let r of bo.keys()){
	console.log(r) // 0 1
}
// 0 1

for(let n of bo.values()){
	console.log(n) 
}
// a c

for(let s of bo.entries()){
	console.log(s)
}
// [0, "a"]
// [1, "c"]
複製程式碼

8. 陣列例項的 includes()

用來表示某個陣列是否包含給定的值,返回一個布林值

let i = ['a',1,2,3]

i.includes()  // false
i.includes(1) // true
i.includes(10) // false
複製程式碼

indexOf 和includes 的區別

indexOf // 不夠語義化,它的作用是找到引數出現的第一個位置,
所以要比較是否為 -1,另外由於 內部使用的是 ===  則導致NaN
的誤判。

// [NaN].indexOf(NaN) // -1

includes // 使用的是不一樣的演算法,則不會有這個問題

// [NaN].includes(NaN) // true
複製程式碼

Map 和 Set 的has 方法和includes的區別

Map 的has 方法是用來查詢鍵名的
Set 的has 方法是用來查詢值的
複製程式碼

9. 陣列的例項 flat(), flatMap()

flat() 將巢狀的二維陣列變成一維陣列,如果需要拉平多維陣列,則flat(多維數量) 或者使用 Infinity 直接轉為一維陣列

let rw = [1,2,3,[4,5,6],7]
rw.flat()  // [1, 2, 3, 4, 5, 6, 7]

let dw =  [1,2,3,[4,5,6,[7,8],[2,['a','b'],4,5]],[5,6,]]
dw.flat(3) // [1, 2, 3, 4, 5, 6, 7, 8, 2, "a", "b", 4, 5, 5, 6]

// 如果你不知道是多少層巢狀而都想轉成一維,可以使用 Infinity
dw.flat(Infinity) 
// [1, 2, 3, 4, 5, 6, 7, 8, 2, "a", "b", 4, 5, 5, 6]
複製程式碼

flatMap() 對陣列執行map,然後對返回值組成的陣列 執行flat,不會改變原陣列。flatMap只能展開一層陣列。

let mp = [2,3,4,5]

mp.flatMap((item) => [item, item* 2])
// [2, 4, 3, 6, 4, 8, 5, 10]
====
mp.map((item) => [item, item*2])
// [[2,4],[3,6],[4,8],[5,10]]
mp.flat()
// [2, 4, 3, 6, 4, 8, 5, 10]    
複製程式碼

10. 陣列的空位(避免出現空位)

陣列的空位指的是該陣列中某一個位置沒有任何值。另外空位不是undefined,如果一個位置的值是undefined,那麼這個位置還是有值的。

Array(3) // [, , ,]
複製程式碼

ES5中大多數情況中對待空位都是會忽略

- forEach(), filter(), reduce(), every() 和 some() 都會跳過空位
- map() 跳過但保留這個值
- join() 和 toString() 中 空位 === undefined,而 undefined和null會被處理成空字串
複製程式碼

ES6 中 空位則轉換為undefined

- Array.from([1,,2]) // [1, undefined, 2]
- [...['a',,'b']]    // [ "a", undefined, "b" ]

entries()
keys()
values()
find()
findIndex()  // 都會將空位處理成undefined。
複製程式碼

歡迎關注 公眾號【小夭同學】

歡迎關注 公眾號【小夭同學】

ES6入門系列

ES6入門之let、cont

ES6入門之變數的解構賦值

ES6入門之字串的擴充套件

ES6入門之正則的擴充套件

ES6入門之數值的擴充套件

ES6入門之函式的擴充套件

Git教程

前端Git基礎教程

相關文章