数组对象
- 一种特殊的对象
- js其实没有真正的数组
- 只是用对象模拟数组
js数组非典型数组
典型数组
- 元素的数据类型相同
- 使用连续内存存储
- 通过数字下标获取元素
js数组不是这样
- 元素的数据类型可以不同
- 内存不一定连续(对象随机存储)
- 不能通过数字下标,而是通过字符串下标
- js数组实际上是对象
- 这意味着数组可以有任何key(key都是字符串)
- 比如
- let arr = [1,2,3]
- arr['xxx'] = 1
创建一个数组
新建
- let arr = [1,2,3]
- let arr = new Array(1,2,3)
- let arr = new Array(3) 参数只有一个,指长度
转化
- let arr = '1,2,3'.split(',')//意为:用逗号分隔
- let arr = '123'.split('')//意为:用空格分隔
- Array.from('123')//最新ES标准提供把不是数组的东西尝试变成数组的方法——条件:0123下标;length属性
伪数组
- let divList = document.querySelectorAll('div')
- 伪数组的原型链中并没有数组的原型
一个数组没有数组共同属性(比如push)的数组就是伪数组
拿到伪数组就要先把它变成数组
合并;两个数组,得到新数组
- arr1.concat(arr2)
截取一个数组的一部分
- arr1.slice(1)//从第二个元素开始
- arr1.slice(0)//全部截取 用于复制数组
- 注意,js只提供浅拷贝slice(0),不提供专门的复制方法
增删改查数组中的元素
1. 删元素
跟对象一样
- let arr = ['a','b','c']
- delete arr['0']
- arr//[empty,'b','c']
- 神奇,数组的长度并没有变
- 稀疏数组(没有好处,都是bug)
如果直接改length可以删元素吗
- let arr = [1,2,3,4,5]
- arr.length = 2
- 居然可以?!js真神奇
- 重要:不要随便改length
删除头部元素
- arr.shift()//arr被修改,并返回被删元素
删除尾部元素
- arr.pop()//arr被修改,并返回被删元素
删除中间元素
- arr.splice(index,1)//删除index的一个元素
- arr.splice(index,1,'x')//并在删除位置添加'x'
- arr.splice(index,1,'x','y')//并在删除位置添加'x','y'
一个对象提供的函数就叫做API,如shift(),pop(),splice()
2. 查看所有元素
查看所有属性名
- let arr = [1,2,3,4,5];arr.x = 'xxx'
- Object.keys(arr)
- for(let key in arr){console.log(
${key}:${arr[ket]})}
针对普通对象可以,数组不建议使用
查看数字(字符串)属性名和值
for(let i = 0;i < arr.length;i++){
console.log(`${key}:${arr[key]}`)//打印属性名,属性值
}
- ${}插入变量
- 你要自己让i从0增长到length-1
arr.forEach(function(item,index){
console.log(`${index}:${item}`)
})
- 也可以用forEach/map等原型上的函数
forEach是一个槛,自己写forEach才能理解forEach
function forEach(array,fn){ //forEach接受一个数组和函数
for(let i = 0;i< array.length;i++){ //当运行forEach的时候,会遍历数组,把i增到length-1
fn(array[i],i,array) //获取数组里的每一项,把每一项作为fn的参数传给fn
}
}
- forEach用for访问array的每一项
- 对每一项调用fn(array[i],i,array)
- 为什么要传入array数组本身呢?
- 不为什么,规定,在特殊情况下会用到,大部分情况下只用传前两项(当前元素和下标)
两种方法for与forEach区别
- 用for用break可以断,forEach要从头走到位
- for后接块作用域,forEach后接函数作用域
3. 查看单个属性
跟对象一样
- let arr = [111,222,333]
- arr[0]
索引越界
- arr[arr.length] === undefined
- arr[-1] === undefined
举例
for(let i = 0;i <= arr.length;i++){ //i只能<length
console.log(arr[i].toString())
}
- 报错:Cannot read property'toString'of undefined
- 解决方法,哪个报错就打印哪个,如console.log(arr[1])
查找某个元素是否在数组里
- arr.indexOf(item)//存在返回索引,否则返回-1
使用条件查找元素
- arr.find(item=>item%2 === 0)//找第一个偶数
使用条件查找元素的索引
- arr.findIndex(item=>item%2 === 0)
- //找第一个偶数索引
4. 增加数组中的元素
尾部加元素
- arr.push(newItem)//修改arr,返回新长度
- arr.push(item1,item2)//修改arr,返回新长度
头部加元素
- arr.unshift(newItem)//修改arr,返回新长度
- arr.unshift(item1,item2)//修改arr,返回新长度
中间加元素
- arr.splice(index,0,'x')//在index处插入'x'
- arr.splice(index,0,'x','y')
5. 修改数组中的元素
反转顺序
- arr.reverse()//修改原数组
经典面试题 如何反转字符串顺序
- 先用API split把字符串换成数组
- 用API reverse 反转数组顺序
- 再把数组变回字符串
自定义顺序
- arr.sort((a,b)=>a-b)
- 简写
数组变化(不会改变原数组)
map
- n变n
filter
- n变少
reduce
- n变1
- 抢钱:包里初始值为零,抢劫一个乘客的钱放包里return,再继续抢,包里的钱加上当前正在抢的乘客的钱等于最终得到的钱
[100,200,300,400].reduce((sum,money)=>{return sum = money},0)
- 有reduce不需要map
- 有reduce不需要filter
题目
第一题
- 把数字变成星期
第二题
- 找出所有大于60分的成绩
第三题
- 算出所有数字之和
面试题
数据变换
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},
]
}