JS数组对象

593 阅读8分钟

数组

  1. JS数组不是典型的数组 典型的数组(如C语言中的数组):
  • 元素的数据类型相同
  • 使用连续的内存存储
  • 通过数字下标获取元素 JS中的数组:
  • 元素的数据类型可以不同
  • 内存不一定是连续的(对象是随机存储的)
  • 不能通过数字下标,而是通过字符串下标
  • 数组可以有任何key,如
    let arr = [1,2,3]
    arr['xxx'] = 1
    

JS的数组实际上是对象,只不过key值是'0','1',且每一个数组在创建后自带length属性,且该属性会自动更新。JS的数组是用key和value来模拟的。

创建一个数组

  1. 新建

    let arr = [1, 2, 3] //简写形式,常用
    let arr = new Array(1, 2, 3) // 正规写法
    let arr = new Array(3) // 当只有一个参数时,设置的时长度
    
  2. 转化

    let arr = '1,2,3'.spllit(',')// 用逗号分隔字符串,结果为["1", "2", "3"]
    let arr = '123'.split('') // 用空字符串分隔,结果为["1", "2", "3"]
    Array.from('123') //尝试转化为数组,可传字符串
    Array.from({0:'a', 1:'b', 2:'c', length: 4} //尝试转化为数组,可传对象,但需要包含length属性
    
  3. 伪数组

    没有数组公用属性(Array.prototype)的数组就是伪数组

  • 伪数组的原型链中没有数组的原型
    array = {0:'a', 1'b', 2:'c', length:3} // 看起来很像数组,但时原型链中没有Array.prototype,其__proto__ === Object.prototype
    
  • 页面所有div,获得的也是伪数组
    let divList = document.querySelectorAll('div')
    
    需要再通过Array.from()转化为数组
    let divArray = Array.from(divList)
    
  1. 合并数组
  • 使用数组对象的concat方法合并两个数组,得到新的数组,不改变原有数组

    let arr1 = [1, 2, 3]
    let arr2 = [4, 5, 6]
    arr1.concat(arr2) // 结果为[1, 2, 3, 4, 5, 6],arr1和arr2不变
    
  • 截取数组

    slice() 方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。

    tips:JS只提供浅拷贝

    let arr = [1, 2, 3, 4, 5, 6]
    arr.slice(1) //从第二个元素开始截取,结果为[2, 3, 4, 5, 6]
    arr.slice(0) //从第一个元素开始截取,等同于复制该数组,注意JS只提供浅拷贝。
    

删除元素

  • (不推荐) 使用和对象的delete方法,对应下标的属性值变为empty,数组的长度不变。这类数组中的元素间存在空隙的称为稀疏数组

    let arr = [1, 2, 3]
    delete arr['0'] //输出为[empty, 2, 3],长度不变
    
  • (不推荐) 修改length,会将键值对调整至与length向匹配的状态,即将length变小,原有的超出范围的键值对将会被删除。

  • 删除头部的元素:arr.shift()

    let arr = [1, 2, 3]
    arr.shift() //返回[2, 3]
    
  • 删除尾部元素:arr.pop()

    let arr = [1, 2, 3]
    arr.pop() //返回[1, 2]
    
  • 删除中间元素:arr.splice() -- 功能强大

    通过删除或替换现有元素或者原地添加新的元素来修改数组,可以使用此方法实现以上的删除方法。

    let arr = [1, 2, 3, 4, 5, 6, 7, 8]
    arr.splice(2, 1) // 指定修改的开始位置为2(从0计数),删除数量为1,返回[1, 2, 4, 5, 6, 7, 8]
    arr.splice(2, 2) // 指定修改的开始位置为2(从0计数),删除数量为1,返回[1, 2, 6, 7, 8]
    //添加
    let arr2 = [1, 2, 3, 4, 5, 6, 7, 8]
    arr2.splice(3, 1, 'x') //指定修改的开始位置为2(从0计数),删除数量为1,同时添加1个值'x', 返回[1, 2, 3, 'x', 5, 6, 7, 8]
    
    let arr3 = [1, 2, 3, 4, 5, 6, 7, 8]
    arr3.splice(3, 1, 'x', 'y')//指定修改的开始位置为2(从0计数),删除数量为1,同时添加1个值'x', 返回[1, 2, 3, 'x', 'y', 5, 6, 7, 8]
    

查看元素

  1. 使用对象的方法查看所有属性名再遍历

    trap:Object.keys(arr)会返回所有属性名,但这并非我们所希望的结果。(从Object角度理解而非Array)

    let arr = [1, 2, 3, 4, 5]
    arr.x = 'x'
    Object.keys(arr) // 返回["0", "1", "2", "3", "4", "x"]
    Object.values(ar) // 返回[1, 2, 3, 4, 5, "x"]
    
  2. 结合for循环与length属性进行遍历

    for(let i = 0; i < arr.length; i++){
        console.log(`${i} : ${arr[i]}`)
    }
    
  3. 使用forEach/map等原型上的函数

    此处使用了回调。(回调的东西之后再补补)

    forEach方法遍历整个数组,每一次都调用所传函数。函数可接收三个参数,item,index,array。

    arr.forEach(function(item, index){
        console.log(`${index} : ${item}`
    

    方法2与方法3的区别:

    • for循环中可以使用break,continue,较forEach方法而言,功能更加强大
    • for为关键字,内部为块级作用域;forEach为函数,内部为函数作用域。(作用域的东西之后再补补)
  4. 查看单个属性

  • 与对象同
    let arr = [1, 2, 3, 4, 5]
    arr[0] // 返回1
    //索引越界的情况
    arr[arr.length] === undefined
    arr[-1] === undefined
    
  1. 查看某个元素是否在数组中
  • 用for循环遍历(不推荐)
  • arr.indexOf(x):返回x在数组中的下标,若不存在则返回-1 arr.find(fn):获取符合条件的数,返回第一个使该函数返回true的值,只会返回第一个值,无下标信息 arr.findIndex(fn):获取符合条件的数的索引,返回第一个使该函数返回true的值的索引,只会返回第一个值,无下标信息
    //使用arr.indexOf(x)获取下标
    let arr = [5, 4, 3, 2, 1]
    arr.indexOf(5) // arr.indexOf(x)返回x在数组中的下标,若不存在则返回-1
    //使用arr.find(fn)
    arr.find((x) => x%5 === 0) //返回第一个为5的倍数的值
    //使用arr.findIndex(fn)
    arr.find((x) => x%2 === 0) //返回第一个偶数的索引
    

增加元素

  1. (不推荐) 直接通过下标增加元素
    let arr=[1,2,3,4,5]
    arr[100] = 1 //arr的length同样修改了,中间其他未赋值的为empty,稀疏数组
    
  2. 在尾部增加元素
    let arr = [1,2,3,4,5]
    arr.push(6, 7) // 返回[1,2,3,4,5,6,7]
    
  3. 在头部增加元素
    let arr = [1,2,3,4,5]
    arr.unshift(6, 7) // 返回[6,7,1,2,3,4,5]
    
  4. 在中间添加 使用arr.splice()
    let arr = [1,2,3,4,5]
    arr.splice(3, 0, 'x', 'y') // 返回[1, 2, 'x', 'y', 3, 4, 5]
    

修改元素

  1. 直接通过下标修改

    let arr=[1,2,3,4,5]
    arr[3]=777   /// 修改下标3数据为777,输出[1, 2, 3, 777, 5]
    
  2. 反转顺序

    arr.reverse(),修改原数组

    let arr=[1,2,3,4,5]
    arr.reverse()  //反转原数组顺序
    

    题目:反转字符串‘abcde’

    思路:

    1. 先将字符串转换为数组对象,
    2. 然后反转数组元素顺序,
    3. 最后再转换回字符串
    //题目:反转字符串‘abcde’
    let s='abcde'
    s.split('').reverse().join('')  //join()方法用于把数组中的所有元素转换一个字符串
    
  3. 自定义顺序

    使用arr.sort()方法,可传入比较方法(compareFunction)来实现自定义排序。

    比较方法compareFunction(a,b):

    • 返回的值大于0(一般使用1),b排在a之前。
    • 返回的值等于0,a 和 b 的相对位置不变。
    • 返回的值小于0(一般使用-1),a排在b之前

    换种方式理解一下,假定sort排序方式为从小到大,返回的值大于0,即表示a>b;等于0,即a与b相等;小于0,即表示a<b。

    arr.sort(function(a,b){
    	if(a>b) {return -1}
        	else if(a===b) {return 0}
        	else {return 1}
        })
    

    按分数排序:

    let arr = [
    	{name:'1', score:99},
        {name:'2', score:95},
        {name:'3', score:100},
    ]
    //简练优化版本
    arr.sort((a,b) => a.score - b.score)
    

数组变换

  1. map:n变n(一一对应)

    let arr = [1,2,3,4,5]
    arr.map(item=>item*item)//一一映射,得到新数组[1,4,9,16,25]
    
  2. filter:n变少(保留符合要求的)

    //题目:把下面数组过滤减少,只保留里面的偶数
    let arr=[1,2,3,4,5,6]
    arr.filter(item=>item % 2 === 0? true : false)  //输出[2,4,6]
    arr.filter(item=>item % 2 === 0) //简写形式
    
  3. reduce:n变1

    reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。(FromMDN)

    reduce为数组中的每一个元素依次执行callback函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:

    • accumulator 累计器
    • currentValue 当前值
    • currentIndex 当前索引
    • array 数组

    题目:把下面数组相加求和

    //题目:把下面数组相加求和
    let arr=[1,2,3,4,5,6]
    arr.reduce((sum,item)=>{return sum+item},0)  //0代表初始值,每一次都把这一轮结果放到赋值给sum
    

    题目:把下面数组每一项变成它的平方,通过reduce实现

    //题目:把下面数组每一项变成它的平方,通过reduce实现
    let arr=[1,2,3,4,5,6]
    arr.reduce((resule,item)=>{return result.concat(item*item)},[])  //初始值为空数组,通过concat把上一次结果和这一次结果连成数组
    

    题目:把下面数组过滤减少,只保留里面的偶数,通过reduce实现

    //题目:把下面数组过滤减少,只保留里面的偶数,通过reduce实现
    let arr = [1, 2, 3, 4, 5, 6];
    arr.reduce((resule, item) => {
      if (item % 2 === 1) {
        return result;
      } else {
        return result.concat(item);
      }
    }, []);
    
    //简写形式
    arr.reduce((result, item) => result.concat(item % 2 === 1 ? [] : item), []);  //每次都要concat,如果是奇数就concat一个空数组[],如果是偶数就concat当前item