JS数组

146 阅读5分钟

1、JS的数组

  • 数组对象,是一种特殊的对象
  • JS其实没有真正的数组,只是用对象模拟数组
  • JS的数组
    • 元素的数据类型可以不同
    • 内存不一定是连续的(对象是随机存储的)
    • 不能通过数字下标,而是通过字符串下标
    • 这意味着数组可以有任何key,如
let arr = [1,2,3]
arr['xxx'] = 1
Object.keys(arr)  //["0","1","2","xxx"]

2、创建数组

  1. 创建方法
let arr = [1,2,3]           //1
let arr = new Array(1,2,3)  //2
let arr = new Array(3)      //3
  1. 转化(把字符串或对象转化为数组,但原来的值不变)
let arr = '1,2,3'; arr.split(',')   //['1','2','3']
let arr = '123'; arr.split('')      //['1','2','3']
Array.from('123')                   //['1','2','3']

3、伪数组

  • let divList = document.querySelectorAll('div')
  • 伪数组的原型链中并没有数组的原型,如
arr = {0:'a',1:'b',2:'c',length:3}      //这是一个伪数组
  • 没有数组属性的“数组”,就是伪数组
  • 拿到伪数组的时候,要把它转化为数组

3、其他创建数组的方法

  1. 合并两个数组,获得一个新的数组
arr1.concat(arr2)
  1. 截取一个数组的一部分,不改变原来的数组
let arr1 = [1,2,3]
arr1.slice(1)              //从第二个元素开始,[2,3]
arr1.slice(0)              //全部截取,用于复制数组,[1,2,3]
let arr2 = arr1.slice(0)   //复制数组
arr1 = [1,2,3]             //arr1没有变化
  • 注意:JS只提供浅拷贝

4、增加数组中的元素

  1. 在尾部增加元素
arr.push('x')       //修改arr,返回新的长度
arr.push('x','y')   //修改arr,在尾部增加元素'x','y',返回新的长度
  1. 在头部加元素
arr.unshift('x')  //修改arr,在头部增加元素'x',然后返回新长度
arr.unshift('x','y')
  1. 在中间加元素
arr.splice(index,0,'x') //在数组下标为index的前面插入'x'
arr.splice(index,0,'x','y') //在数组下标为index的前面插入'x'
  • 实例:

5、删除数组中的元素

  1. 跟对象一样
let arr = ['a','b','c']
delete arr['0']
arr     //[empty,'b','c'],length=3

神奇,数组的长度并没有变

  • 稀疏数组:有length长度,元素大多为empty的数组
  1. 如果直接改length,可以删除元素吗?
let arr = [1,2,3,4,5]
arr.length = 1
arr     //arr===[1],真的可以,但是会报错
  • 重要:不要随便改length
  1. 正确的删除方法:
  • 删除头部的元素
arr.shift()    //arr被修改,并返回被删元素

示例:

  • 删除尾部的元素
arr.pop()      //arr被修改,并返回被删元素

示例:

  • 删除中间的元素
arr.splice(x,1)                 //删除arr[x]的一个元素
arr.splice(x,1,'x')             //并在删除位置添加'x'
arr.splice(x,1,'x','y')         //并在删除位置添加'x','y'

示例:

6、修改数组中的元素

  1. 反转顺序
arr.reverse()  //翻转顺序,并修改原数组
  1. 反转字符串
let x='abcde'
x.split('')   //['a','b','c','d','e']
x.split('').reverse()   // ['e','d','c','b','a']
x.split('').reverse().join('')  //“edcba”
  • join() 方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串
  1. 自定义顺序
arr.sort()  //会改变数组自身
let arr = [2,4,1,6,3]
arr.sort()                     //arr=[1,2,3,4,6]
arr.sort(function(a,b){        //arr.sort()的原理
    if(a>b){
        return 1
    }else if(a===b){
        return 0   
    }else{
        return -1
    }
})

arr.sort(function(a,b){        //返回arr[6,4,3,2,1]
    if(a>b){ 
        return -1
    }else if(a===b){
        return 0
    }else{
        return 1
    }
})
  • 如果数组的元素是对象呢?
let arr = [
    {name:'小明',score:80},{name:'小红',score:90},{name:'小蓝',score:85}    
]
arr.sort(function(a,b){   
    if(a.score > b.score){
        return 1
    }else if(a.score === b.score){
        return 0
    }else{
        return -1    
    }
})

结果:

  • arr.sort(function}(a,b){........})的简易写法:
arr.sort((a,b)=>a-b)  //数组元素为数字
arr.sort((a,b)=>a.score - b.score)   //数组元素为对象,比较某个值
arr.sort((a,b)=>-(a.score - b.score)) //反向排序

7、查看数组中的元素

  • 查看数组的属性名(更适用于对象,而不是数组,可以输出属性名不是顺序的属性名,如'x')
  • for...in 适用于返回对象
Object.keys(arr)             //方法一,更适用于对象
for (let key in arr){        //方法二,更适用于对象
    console.log(`${key}:${arr[key]}`)
}
  • 正确方法:
  1. 查看数字(字符串)属性名和值
for(let i=0;i<arr.length;i++){
    console.log(`${i}: ${arr[i]}`)
}

示例:

  1. 数组自带的API,用于遍历数组
arr.forEach(function(item,index){     //item是数组的元素,index是数组的下标,可以是任意值
    console.log(`${index}: ${item}`)
})       

示例:

  • 理解forEach
function forEach(array, fn){
    for(let i=0;i<array.length;i++){
        fn(array[i],i)
    }
}
forEach(['a','b','c'], function(x){
    console.log(x)
})                                 
//输出a,b,c
function forEach(array, fn){    
    for(let i=0;i<array.length;i++){
        fn(array[i],i)    
    }}
forEach(['a','b','c'], function(x,y){    
    console.log(x,y)
})   
//输出 a 0;b 1;c 2
  • forEach()方法的三个参数,x:数组元素,y:数组下标,z:整个数组

示例:

  • forEach()方法与for循环的区别
    • for是一个关键字,forEach()是一个方法
    • for循环支持break和continue,forEach()不支持
    • for循环是一个块级作用域,forEach()是一个函数作用域
  1. 查看单个属性
  • 跟对象一样
let arr=[11,22,33]
arr[0]       //11
  • 索引越界
    • arr[arr.length] === undefined
    • arr[-1] === undefined
    • 举例:
for(let i=0;i<=arr.length;i++){
    console.log(arr[i].toString())
}
// 报错:Cannot read property 'toString' of undefined
  • Cannot read property 'toString' of undefined 意思是读取了undefined 的toString属性,不是toString是undefined, x.tostring() 其中x如果是undefined 就会报这个错
  1. 查找某个元素是否在数组里
arr.indexOf(item)  //存在的话,返回数组下标,不存在返回-1

示例:

  1. 使用条件查找元素
arr.find(function(x){
    return x%2===0  //如果x%2===0为true,则停止,返回并输出这个元素,但只会返回符合条件的第一个数
})

arr.findIndex(function(x){
    return x%2===0  //返回对应元素的下标
})

示例:

8、数组变换

  1. map(不会改变原数组)
  • n变n
  • 示例:
let arr = [1,2,3,4,5,6]
arr.map(item => item*item) //返回[1,4,9,16,25,36]
  1. filter(不会改变原数组)
  • n变少
  • 示例:
let arr = [1,2,3,4,5,6]
arr.filter(item => item% 2 ===0)   //返回[2,4,6]
  1. reduce(不会改变原数组)
  • n变1
  • 示例1
let arr = [1,2,3,4,5,6]
arr.reduce((sum,item) => {return sum+item},0)   //返回21
  • 示例2(reduce()代替map())`
let arr = [1,2,3,4,5,6]
arr.reduce((result,item) => {retrun result.concat(item*item)},[])  //[1,4,9,16,25,36]
  • 示例3(reduce()代替filter())
let arr = [1,2,3,4,5,6]
arr.reduce((result,item)=>{
    if(item%2 === 1){
        return result
    }else{
        return result.concat(item)
    }
},[])              //[2,4,6]
arr.reduce((result,item)=>result.concat(item%2 === 1?[]:item),[])    //简化版

9、面试题

let arr = [
    {名称:'动物', id:1 , parent:null},
    {名称:'狗', id:2 ,parent:1},
    {名称:'猫', id:3 ,parent:1}
]

要求把数组变成对象

{
    id:1 ,名称:'动物',children:[
        {id:2 , 名称:'狗', children:null},
        {id:3 , 名称:'猫', children:null}
    ]
}

答案:

arr.reduce((result,item) =>{
    if(item.parent === null){
        result.id = item.id
        result['名称'] = item['名称']
    }else{
        item.children = null
        result.children.push(item)
        delete item.parent
    }
    return result
},{id:null,children:[]})