JS常用数组操作全解析

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]

let arr = [].join.call('13421212341', ',')  // string可使用的array方法
console.log(arr)  // 1,3,4,2,1,2,1,2,3,4,1

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]

let arr = [].slice.call('13421212341', 0, 5) // string可使用的array方法
console.log(arr)		// ["1", "3", "4", "2", "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不会改变原始数组

map的五种用途

在数组的每一项上调用一个函数

const sweetArray = [2, 3, 4, 5, 35]
const sweeterArray = sweetArray.map(sweetItem => {
    return sweetItem * 2
})
console.log(sweetArray)   // [2, 3, 4, 5, 35]
console.log(sweeterArray) // [4, 6, 8, 10, 70]

源数组并没有被修改,可简写为

// 创建一个要使用的函数
const makeSweeter = sweetItem => sweetItem * 2;
// 我们有一个数组
const sweetArray = [2, 3, 4, 5, 35];
// 调用我们制作的函数。更具可读性
const sweeterArray = sweetArray.map(makeSweeter);
console.log(sweeterArray); // [4, 6, 8, 10, 70]

将字符串转化为数组

const name = "Chuloo"
const map = Array.prototype.map
const newName = map.call(name, eachLetter => {
    return `${eachLetter}a`
})
console.log(newName) // ["Ca", "ha", "ua", "la", "oa", "oa"]

在React中用于渲染列表

import React from "react";
import ReactDOM from "react-dom";
const names = ["john", "sean", "mike", "jean", "chris"];
const NamesList = () => (
{names.map(name => 
 {name} )}
);
const rootElement = document.getElementById("root");
ReactDOM.render(, rootElement);

重新格式化数组对象

const myUsers = [
{ name: 'chuloo', likes: 'grilled chicken' },
{ name: 'chris', likes: 'cold beer' },
{ name: 'sam', likes: 'fish biscuits' }
]
const usersByFood = myUsers.map(item => {
    const container = {};
    container[item.name] = item.likes;
    container.age = item.name.length * 10;
    return container;
})
console.log(usersByFood);
// [{chuloo: "grilled chicken", age: 60}, {chris: "cold beer", age: 50}, {sam: "fish biscuits", age: 30}]

小技巧

map下的callback方法,接受三个参数:item、index、arr,第三个为调用map的数组本身,常被忽略

// 下面的语句返回什么呢:
["1", "2", "3"].map(parseInt);
// 你可能觉的会是[1, 2, 3]
// 但实际的结果是 [1, NaN, NaN]
// 通常使用parseInt时,只需要传递一个参数.
// 但实际上,parseInt可以有两个参数.第二个参数是进制数.
// 可以通过语句"alert(parseInt.length)===2"来验证.
// map方法在调用callback函数时,会给它传递三个参数:当前正在遍历的元素, 
// 元素索引, 原数组本身.
// 第三个参数parseInt会忽视, 但第二个参数不会,也就是说,
// parseInt把传过来的索引值当成进制数来使用.从而返回了NaN.
function returnInt(element) {
return parseInt(element, 10);
}
['1', '2', '3'].map(returnInt); // [1, 2, 3]
// 意料之中的结果
// 也可以使用简单的箭头函数,结果同上
['1', '2', '3'].map( str => parseInt(str) );
// 一个更简单的方式:
['1', '2', '3'].map(Number); // [1, 2, 3]
// 与`parseInt` 不同,下面的结果会返回浮点数或指数:
['1.1', '2.2e2', '3e300'].map(Number); // [1.1, 220, 3e+300]

.map().reduce(), .filter() 这些方法支持链式调用

var myArr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var result = myArr
.map(function(element) {
    // 数值大于5的数值视为5
    if (element > 5)
    return 5;
    return element;
})
.reduce(function(prev, element) {
    // 与之前的数值加总,回传后代入下一轮的处理
    return prev + element;
}, 0);

console.log(result);	// 40

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即使上一次累加的结果


实践应用
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
}, [])

循环次数减少了一半,推荐

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值