定义
JS中的数组是一种特殊的对象,没有真正的数组,只是对象模拟数组
典型数组、JS数组对比
- 典型数组
- 元素的数据类型相同
- 使用连续的内存存储元素
- 通过数字下标获取元素
- JS数组
- 元素的数据类型可以不同
- 内存不一定是连续的(对象是随机存储的)
3. 不能通过数字下标,而是字符串下标
4. 以上意味着数组可以有任何key
例:
创建数组arr,其中有三个对象。现加入新对象,对象key为'xxx'字符串,value为1字符串,所以数组可以有任何key
创建一个数组
新建数组
let arr=[1,2,3]通俗写法ler arr=new Array(1,2,3)构造对象写法,与以上等价let arr=new Array(3)数组内对象的数量为3个
转化
- split(',') 用','分割字符串,(字符串含有逗号)
str对象为'1,2,3'字符串,用,分割成三个字符串
- split('') 用空格分割字符串(字符串紧密相连)
str对象为'123'字符串,使用空格,将其分成三个字符串
- Array.from
不能变成数组
有下标和length属性的对象可以变成数组,新数组的length以原对象的length为准,多出部分直接提出,如:这里的length:3,那么转化成的数组为[''a'',''b'']
为什么数组只支持字符串?
以arry=[1,2,3]为例,里面的1对象自带toString属性,自动转为字符串。即使是数字也会转化为字符串
伪数组
伪数组原型链中并没有数组的原型,所以要先利用转换属性转换成数组
以array={0:1,1:2,2:3}为例,它的原型为Object,没有字符串原型对应的push等属性,所以array为对象
合并、切割、复制数组
合并数组
- 拼接
arr3.concat(arr4):调用arr3的concat属性,以自身为基础,在后面拼接出一个新的数组,原来的arr3,arr4数组没有变化
切割(截取)数组
arr1.slice(n) 从第n个元素开始截取,原数组不变
拷贝 (从0开始截取)
多用于拷贝一个数组
- 注意 JS只提供浅拷贝
元素的增删改查
删元素
- delete arr[i](第i个)
删除第0个字符串'a',字符串长度不变,原有的项目还存在,只是空的,arr即为稀疏数组
- 改数组长度
数组长度为5,改变length属性,长度变为1,仅剩下1。因此不要随便改length,某些情况下影响数组的调用
- 删除头部元素
arr被修改,并返回被删元素
- 删除尾部元素
arr被修改,并返回删除元素5
- 删除中间的元素 arr.splice(index,n,'x','y')
- index:从第几个开始删(取值0,1,2,3,4)
- n:删几个
- 'x','y':加上什么,可写多个
查看所有元素
查看所有属性名
- Object.keys(arr)和for循环法
例声明一个数组[1,2,3,4],其中另外加入key:xxx,value为x
Object法,直接输出了所有key,即0,1,2,3,4,x
for循环,直接输出每个key和对应的value
这两种方法都是输出后面添加的xxx属性,存在局限性 - for each
- 循环法
引入变量i,控制条件为length-1,等于length终止,所以调用keys的时候只能调用数字形式,避开了x
- forEach调用函数
调用forEach原型上的函数,item为value对应参数,index为key对应参数,两个参数名字可以随便取
forEach原理
- forEach用for访问array的每一项
- 对每一项调用fn(array[i],i,array)
- 为什么要传入array? 规定如此
查看单个属性
跟对象一样
索引越界
此时arr[arr.length]等价于arr[4],数组下标从0-3,不存在4,所以返回undefined
同理,数组不存在下标-1,所以返回undefined
- 举例证明
最后一次循环报错,i等于length,超出下标,反之,去掉= 号,代码不报错
查找某个元素是否在数组里
- arry。indexOf(item) 存在返回索引,否则返回-1
以上案例显示两种方法:
- 循环遍历,方法较为基础,繁琐
- arry.indexOf(item),固定写法,括号内为所要查找的元素,存在,返回顺序值,不存在返回-1
使用条件查找元素
- arr.find(item=> %2===0) 找到第一个偶数
- arr.findIndex(item=>item%2==0) 找到第一个偶数的索引
增加数组中的元素
在尾部添加元素
- arr.push(newItem) 修改原来数组,返回新长度,newItem可写多个
在头部添加元素
- arr.unshift(newItem) 用法同上
在中间添加元素
- arr.splice(地址,删几个(取0一个都不删),新增内容)新增的内容可以写多个
修改数组中的元素
反转顺序
- arr.reverse() 修改了原来的数组
小应用
- 如何反转字符串abcde
思路: s不能直接反转,先转成数组,数组反转,再讲数组拼接成字符串
自定义顺序
- arr.sort() 默认从小到大排列
- 按数值从小到大排列(同上效果)
- 按数值从大到小(多用于排名)比如成绩排名
小应用
把对象进行排序
思路:sort引用函数,将每个对象类比成单个元素,元素再调用score,再用return:1/-1/0进行判断
简写:原理类似于return, 隐含着逻辑:二者相减 a>b返回正数,a===b返回0,a<b返回负数
如果按照成绩排名排,那么b的score减去a的
数组变换
抽象概览(以下三种操作不会改变原数组)
1.map(应用场景:数组元素逐个变换)
数组各个元素变成平方,参数item可任意取名
2.filter(应用场景:特定条件筛选功能)
提取偶数
3.reduce(应用场景:对数组进行变换,转化为不同形式的对象,灵活多变)
数组求和 ,参数 1:结果,数组元素 2:变化的规则 3:结果的初始值
reduce思想模型:上车打劫
如图:小人手中的袋子为结果,其中的0为初始值,红色数字为数组各项值,红色箭头部分(将钱装入口袋的过程)为执行的操作
用reduce得到数组元素平方
思路 传入参数result:返回的数组,初始值为[]空数组、参数item。调用concat,空数组与元素平方拼接,循环6次,得到元素平方的数组
逻辑图解
用reduce实现filter效果 例:筛选出偶数
- 循环法思路:result为空数组,如果为基数,返回result,反之为偶数,调用concat将item放入result中,如此循环
- 初次简化思路: 思想同上
- 最终简化 思路:result初始值为[],直接一次性调用concat属性,属性内部加入判断语句。 如果item为奇数,result拼接空数组[](等价于什么都没加),如果判断为偶数,result拼接item 如此循环,得出数组
综合案例
解题
arr.reduce((result, item) => { 引出两个参数result,item
if (item.parent === null) { '动物' 对象的parent值为null 作为筛选第一条件
result.id = item.id 筛选出了为null 的item, result的id为当前item的id
result['名称'] = item['名称'] result的名称为当前item的名称
} else { 不是动物 对象
result.children.push(item) result的children属性内加入另外两个对象
delete item.parent childre里的对象自带parent属性,所以将其删除
item.children = null children里面的对象添加children属性,值为null
}
return result 判断执行结束,返回结果
}, { id: null, children: [] }) 初始化结果