JS常用陣列操作全解析

.醬發表於2018-11-07
concat() 方法用於連線兩個或多個陣列。
let arr1 = [1, 3, 4, 5]
let arr2 = ['11', '1']
let arr3 = [{ a: 1 }, { b: 2 }]
let all = arr1.concat(arr2).concat(arr3)
console.log(all) // [1, 3, 4, 5, "11", "1", {…}, {…}]
複製程式碼
concat()方法,不會改變原陣列本身

join(separator)把陣列中每一項提取出來並用指定字元分割組成字串
let arr1 = [1, 3, 4, 5, [1, 2, 3]]
let arr2 = ['11', '1']
let arr3 = [{ a: 1 }, { b: 2 }]
let all = arr1.concat(arr2).concat(arr3)
let str = all.join('v')
console.log(str) // 1v3v4v5v1,2,3v11v1v[object Object]v[object Object]
複製程式碼

separator為join方法暴露的引數,預設為','。**注意:**join可以提取String和Number但是無法解析物件中的資料


pop()刪除陣列最後一項,並返回被刪除項,如果陣列長度為0,則返回undefined
let arr1 = [0, 1, 2, 3, 4]
let str = arr1.pop()
console.log(str)	// 4
console.log(arr1)	// [0, 1, 2, 3]
複製程式碼

**注意:**pop()會改變源陣列


push()方法可向陣列的末尾新增一個或多個元素,並返回新的長度
let arr1 = [0, 1, 2, 3, 4]
let str = arr1.push([5, 6])
console.log(str)	// 6
console.log(arr1) // [0, 1, 2, 3, 4, Array(2)]
複製程式碼

**注意:**push()後向陣列末尾新增指定資料,無論他什麼型別,即使是NaN也會切只會佔據陣列中一個位置


reverse()顛倒陣列中元素位置
let arr1 = [0, 1, 2, 3, 4]
let str = arr1.reverse()
console.log(str)	// [4, 3, 2, 1, 0]
console.log(arr1)	// [4, 3, 2, 1, 0]
複製程式碼

**注意:**此操作會改變源陣列


shift()刪除陣列第一個元素,並返回被刪除元素
let arr1 = [0, 1, 2, 3, 4]
let str = arr1.shift()
console.log(str)	// 0
console.log(arr1)	// [1, 2, 3, 4]
複製程式碼

**注意:**此操作會改變源陣列


slice(start, end)從已有陣列中選定一個範圍組成子陣列
let arr1 = [0, 1, 2, 3, 4]
let arr2 = arr1.slice(1, 3)
let arr3 = arr1.slice(-1)
let arr4 = arr1.slice(1, -3)
console.log(arr1)	// [0, 1, 2, 3, 4]
console.log(arr2)	// [1, 2]
console.log(arr3)	// [4]
console.log(arr4)	// [1]
複製程式碼

注意: start為必填項,確定開始位置,正數為順序查詢,負數為倒序查詢;end為選填項,確定結束位置,預設為至最後一項


sort(sortby)對陣列進行排序
**普通陣列**
sortNumber (a, b) {
    return a - b
},
learnArray () {
    let arr1 = ['10', '131', '234', '111', '20', '002', '0071']

    console.log(arr1.sort())	// ["002", "0071", "10", "111", "131", "20", "234"]
    console.log(arr1.sort(this.sortNumber))	// ["002", "10", "20", "0071", "111", "131", "234"]
}

**陣列中的物件未處理前無法排序**
learnArray () {
    let arr = []
    for (let i = 0; i < 5; i++) {
        arr.push({i: i * Math.random()})
        console.log(arr[i], arr[i].length)
    }

    console.log(arr.sort())
    // 0:{i: 0}
    // 1:{i: 0.16355624558752946}
    // 2:{i: 1.7387739842785384}
    // 3:{i: 0.3757190308241345}
    // 4:{i: 3.160518025347579}
}


**經過特殊處理後的陣列**
sortNumber (a, b) {
    let obj1 = a['i']
    let obj2 = b['i']
    return obj2 - obj1
},
learnArray () {
    let arr = []
    for (let i = 0; i < 5; i++) {
        arr.push({i: i * Math.random()})
        console.log(arr[i], arr[i].length)
    }

    console.log(arr.sort())
    // 0:{i: 3.8106310267596397}
    // 1:{i: 1.3285710809611437}
    // 2:{i: 1.0776123310362173}
    // 3:{i: 0.9429327310688747}
    // 4:{i: 0}
    console.log(arr.sort(this.sortNumber))
    // 0:{i: 3.8106310267596397}
    // 1:{i: 1.3285710809611437}
    // 2:{i: 1.0776123310362173}
    // 3:{i: 0.9429327310688747}
    // 4:{i: 0}
}
複製程式碼

**注意:**sort()接受一個函式作為排序條件,預設按照字母順序排列,函式的返回值應該是一個比較的結果,正數(正序)、負數(倒序)、或NAN(走預設排序),比較物件應該為由數字、字母任意組成的字串,如果為sort傳遞了排序條件,預設排序會繼承


splice(index,howmany,item1,.....,itemX)從陣列中新增/刪除元素
let arr = []
let arr1 = arr.splice(0, 0, 1)
console.log(arr)		// [1]
console.log(arr1)		// []
複製程式碼

index為起始位置,howmany為要刪除專案數量,可以為0,item要新增的元素,splice方法會返回被刪除的元素,並會改變原陣列


toString將陣列轉換為物件並返回

結果與沒有引數的join()方法一致,不會改變源陣列


unshift在陣列開頭新增一個元素,並返回新長度

unshift會改變源陣列,可以通過arr.unshift()拿到arr的長度


forEach
let arr1 = [1, 2, 3, {a: 1}, 5]
arr1.forEach((item, index) => {
    if (item.a) {
        item.a += 1
    } else {
        item += 1
    }
})
console.log(arr1)
// 0:1
// 1:2
// 2:3
// 3:{a: 2}
// 4:5
複製程式碼

forEach遍歷出來的物件會被直接更改,原因是JS中物件傳值引用傳遞,傳遞的是記憶體地址,修改後會改變記憶體地址對應儲存的值。而非物件只是進行了值傳遞,函式中可以用這個值,但是無法修改。

**注意:**forEach很容易修改原始陣列的值


map
let arr1 = [1, 2, 3, {a: 1}, 5]
let arr2 = arr1.map((item, index) => {
    let imap
    if (item.a) {
        imap = item.a + 1
    } else {
        imap = item + 1
    }
    return imap
})
console.log(arr1)
// 0:1
// 1:2
// 2:3
// 3:{a: 1}
// 4:5
console.log(arr2)
// 0:1
// 1:2
// 2:3
// 3:2
// 4:5
複製程式碼

map需要有一個返回值,並且有新陣列來接收最終資料,一般情況下map不會改變原始陣列


every
isBelowThreshold(currentValue) {
  return currentValue < 40
}

let array1 = [1, 30, 39, 29, 10, 13]

console.log(array1.every(isBelowThreshold)) // true
複製程式碼

every會將陣列中每一項作為引數,傳遞給指定函式,返回值均為true則最終結果為true,相當於&&


some
isBelowThreshold(currentValue) {
  return currentValue > 39
}

let array1 = [1, 30, 39, 29, 10, 13]

console.log(array1.some(isBelowThreshold)) // true
複製程式碼

every會將陣列中每一項作為引數,傳遞給指定函式,返回值有一項為true則最終結果為true,相當於||


filter
isBelowThreshold (currentValue) {
    return currentValue > 20
},

learnArray () {
    let array1 = [1, 30, 39, 29, 10, 13]

    console.log(array1.filter(this.isBelowThreshold)) // [30, 39, 29]
}
複製程式碼

filte同樣會建陣列中每一項作為引數,傳遞給函式進行過濾


reduce
getSum (total, num) {
    return Math.round(total) + Math.round(num)
},
learnArray () {
    let numbers = [15.5, 2.3, 1.1, 4.7]
    console.log(numbers.reduce(this.getSum)) // 24
}
複製程式碼

reduce可以看做是一個累加器,從做開始依次執行,值得注意的是第一次執行是total作為初始值,之後執行total即使上一次累加的結果

concat() 方法用於連線兩個或多個陣列。
let arr1 = [1, 3, 4, 5]
let arr2 = ['11', '1']
let arr3 = [{ a: 1 }, { b: 2 }]
let all = arr1.concat(arr2).concat(arr3)
console.log(all) // [1, 3, 4, 5, "11", "1", {…}, {…}]
複製程式碼
concat()方法,不會改變原陣列本身

join(separator)把陣列中每一項提取出來並用指定字元分割組成字串
let arr1 = [1, 3, 4, 5, [1, 2, 3]]
let arr2 = ['11', '1']
let arr3 = [{ a: 1 }, { b: 2 }]
let all = arr1.concat(arr2).concat(arr3)
let str = all.join('v')
console.log(str) // 1v3v4v5v1,2,3v11v1v[object Object]v[object Object]
複製程式碼

separator為join方法暴露的引數,預設為','。**注意:**join可以提取String和Number但是無法解析物件中的資料


pop()刪除陣列最後一項,並返回被刪除項,如果陣列長度為0,則返回undefined
let arr1 = [0, 1, 2, 3, 4]
let str = arr1.pop()
console.log(str)	// 4
console.log(arr1)	// [0, 1, 2, 3]
複製程式碼

**注意:**pop()會改變源陣列


push()方法可向陣列的末尾新增一個或多個元素,並返回新的長度
let arr1 = [0, 1, 2, 3, 4]
let str = arr1.push([5, 6])
console.log(str)	// 6
console.log(arr1) // [0, 1, 2, 3, 4, Array(2)]
複製程式碼

**注意:**push()後向陣列末尾新增指定資料,無論他什麼型別,即使是NaN也會切只會佔據陣列中一個位置


reverse()顛倒陣列中元素位置
let arr1 = [0, 1, 2, 3, 4]
let str = arr1.reverse()
console.log(str)	// [4, 3, 2, 1, 0]
console.log(arr1)	// [4, 3, 2, 1, 0]
複製程式碼

**注意:**此操作會改變源陣列


shift()刪除陣列第一個元素,並返回被刪除元素
let arr1 = [0, 1, 2, 3, 4]
let str = arr1.shift()
console.log(str)	// 0
console.log(arr1)	// [1, 2, 3, 4]
複製程式碼

**注意:**此操作會改變源陣列


slice(start, end)從已有陣列中選定一個範圍組成子陣列
let arr1 = [0, 1, 2, 3, 4]
let arr2 = arr1.slice(1, 3)
let arr3 = arr1.slice(-1)
let arr4 = arr1.slice(1, -3)
console.log(arr1)	// [0, 1, 2, 3, 4]
console.log(arr2)	// [1, 2]
console.log(arr3)	// [4]
console.log(arr4)	// [1]
複製程式碼

注意: start為必填項,確定開始位置,正數為順序查詢,負數為倒序查詢;end為選填項,確定結束位置,預設為至最後一項


sort(sortby)對陣列進行排序
**普通陣列**
sortNumber (a, b) {
    return a - b
},
learnArray () {
    let arr1 = ['10', '131', '234', '111', '20', '002', '0071']

    console.log(arr1.sort())	// ["002", "0071", "10", "111", "131", "20", "234"]
    console.log(arr1.sort(this.sortNumber))	// ["002", "10", "20", "0071", "111", "131", "234"]
}

**陣列中的物件未處理前無法排序**
learnArray () {
    let arr = []
    for (let i = 0; i < 5; i++) {
        arr.push({i: i * Math.random()})
        console.log(arr[i], arr[i].length)
    }

    console.log(arr.sort())
    // 0:{i: 0}
    // 1:{i: 0.16355624558752946}
    // 2:{i: 1.7387739842785384}
    // 3:{i: 0.3757190308241345}
    // 4:{i: 3.160518025347579}
}


**經過特殊處理後的陣列**
sortNumber (a, b) {
    let obj1 = a['i']
    let obj2 = b['i']
    return obj2 - obj1
},
learnArray () {
    let arr = []
    for (let i = 0; i < 5; i++) {
        arr.push({i: i * Math.random()})
        console.log(arr[i], arr[i].length)
    }

    console.log(arr.sort())
    // 0:{i: 3.8106310267596397}
    // 1:{i: 1.3285710809611437}
    // 2:{i: 1.0776123310362173}
    // 3:{i: 0.9429327310688747}
    // 4:{i: 0}
    console.log(arr.sort(this.sortNumber))
    // 0:{i: 3.8106310267596397}
    // 1:{i: 1.3285710809611437}
    // 2:{i: 1.0776123310362173}
    // 3:{i: 0.9429327310688747}
    // 4:{i: 0}
}
複製程式碼

**注意:**sort()接受一個函式作為排序條件,預設按照字母順序排列,函式的返回值應該是一個比較的結果,正數(正序)、負數(倒序)、或NAN(走預設排序),比較物件應該為由數字、字母任意組成的字串,如果為sort傳遞了排序條件,預設排序會繼承


splice(index,howmany,item1,.....,itemX)從陣列中新增/刪除元素
let arr = []
let arr1 = arr.splice(0, 0, 1)
console.log(arr)		// [1]
console.log(arr1)		// []
複製程式碼

index為起始位置,howmany為要刪除專案數量,可以為0,item要新增的元素,splice方法會返回被刪除的元素,並會改變原陣列


toString將陣列轉換為物件並返回

結果與沒有引數的join()方法一致,不會改變源陣列


unshift在陣列開頭新增一個元素,並返回新長度

unshift會改變源陣列,可以通過arr.unshift()拿到arr的長度


forEach
let arr1 = [1, 2, 3, {a: 1}, 5]
arr1.forEach((item, index) => {
    if (item.a) {
        item.a += 1
    } else {
        item += 1
    }
})
console.log(arr1)
// 0:1
// 1:2
// 2:3
// 3:{a: 2}
// 4:5
複製程式碼

forEach遍歷出來的物件會被直接更改,原因是JS中物件傳值引用傳遞,傳遞的是記憶體地址,修改後會改變記憶體地址對應儲存的值。而非物件只是進行了值傳遞,函式中可以用這個值,但是無法修改。

**注意:**forEach很容易修改原始陣列的值


map
let arr1 = [1, 2, 3, {a: 1}, 5]
let arr2 = arr1.map((item, index) => {
    let imap
    if (item.a) {
        imap = item.a + 1
    } else {
        imap = item + 1
    }
    return imap
})
console.log(arr1)
// 0:1
// 1:2
// 2:3
// 3:{a: 1}
// 4:5
console.log(arr2)
// 0:1
// 1:2
// 2:3
// 3:2
// 4:5
複製程式碼

map需要有一個返回值,並且有新陣列來接收最終資料,一般情況下map不會改變原始陣列


every
isBelowThreshold(currentValue) {
  return currentValue < 40
}

let array1 = [1, 30, 39, 29, 10, 13]

console.log(array1.every(isBelowThreshold)) // true
複製程式碼

every會將陣列中每一項作為引數,傳遞給指定函式,返回值均為true則最終結果為true,相當於&&


some
isBelowThreshold(currentValue) {
  return currentValue > 39
}

let array1 = [1, 30, 39, 29, 10, 13]

console.log(array1.some(isBelowThreshold)) // true
複製程式碼

every會將陣列中每一項作為引數,傳遞給指定函式,返回值有一項為true則最終結果為true,相當於||


filter
isBelowThreshold (currentValue) {
    return currentValue > 20
},

learnArray () {
    let array1 = [1, 30, 39, 29, 10, 13]

    console.log(array1.filter(this.isBelowThreshold)) // [30, 39, 29]
}
複製程式碼

filte同樣會建陣列中每一項作為引數,傳遞給函式進行過濾


reduce
getSum (total, num) {
    return Math.round(total) + Math.round(num)
},
learnArray () {
    let numbers = [15.5, 2.3, 1.1, 4.7]
    console.log(numbers.reduce(this.getSum)) // 24
}
複製程式碼

reduce可以看做是一個累加器,從做開始依次執行,值得注意的是如果不指定初始值第一次執行是total作為初始值也就是陣列的第一個元素,之後執行total即使上一次累加的結果

另:reduce接收兩個引數第一個為回撥函式,第二個是初始值,也就是這裡的total它非必傳


實踐應用
let old = [
    {
        id: 1,
        name: 'css',
        type: 'html'
    },
    {
        id: 3,
        name: 'javacript',
        type: 'code'
    },
    {
        id: 5,
        name: 'css',
        type: 'html'
    }
]
複製程式碼

有一個陣列,期望把相同name的物件合併,並且把對應的id放到一個陣列

方法一、

let arr = []
old.forEach((item) => {
    let str = JSON.stringify(old)
    if (str.indexOf(item.type) === -1) {
        let obj = {
            id: [item.id],
            name: item.name,
            type: item.type
        }
        arr.push(obj)
    } else {
        arr.forEach((items) => {
            if (items.type === item.type) items.id.push(item.id)
        })
    }
})
複製程式碼

需要n^2次的迴圈,不推薦

方法二、

let isEqual = (a, b) => a.name === b.name && b.type === b.type // 判斷條件
let create = e => {	// 建立新物件
    e.id = [e.id]
    return e
}

let getNew = old => old.reduce((acc, cur) => {
    let hasItem = acc.some(e => {
    let temp = isEqual(e, cur)
    if (temp) e.id.push(cur.id)

    return temp
})

if (!hasItem) acc.push(create(cur))
    return acc
}, [])
複製程式碼

迴圈次數減少了一半,推薦

相關文章