JS数组

185 阅读6分钟

定义

JS中的数组是一种特殊的对象,没有真正的数组,只是对象模拟数组

典型数组、JS数组对比

  • 典型数组
    1. 元素的数据类型相同
    2. 使用连续的内存存储元素
    3. 通过数字下标获取元素 7521acf71d3926195105a0d8d76362d.png
  • JS数组
    1. 元素的数据类型可以不同
    2. 内存不一定是连续的(对象是随机存储的)

524564ce5fd7750ad6aa9c057043500.png 3. 不能通过数字下标,而是字符串下标 4. 以上意味着数组可以有任何key

例:

ad8d753e040f43e0cfd0bb5e8bda659.png
创建数组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(',') 用','分割字符串,(字符串含有逗号)

68577a70ec1ad6a657fb0f9bdef803a.png
str对象为'1,2,3'字符串,用,分割成三个字符串

  • split('') 用空格分割字符串(字符串紧密相连)

717dc164e0bb5597f4a2be3d937211b.png
str对象为'123'字符串,使用空格,将其分成三个字符串

  • Array.from

35f7cc30bac14eb5322766ceeca33f9.png
不能变成数组

884befedf04dc1fa7f57a676d6e8bc2.png
有下标和length属性的对象可以变成数组,新数组的length以原对象的length为准,多出部分直接提出,如:这里的length:3,那么转化成的数组为[''a'',''b'']

为什么数组只支持字符串?

0b86eef9d50f4e58abe5f72a53af20b.png
以arry=[1,2,3]为例,里面的1对象自带toString属性,自动转为字符串。即使是数字也会转化为字符串

伪数组

伪数组原型链中并没有数组的原型,所以要先利用转换属性转换成数组

1580af4dae0c986ad576591d57dd5be.png
以array={0:1,1:2,2:3}为例,它的原型为Object,没有字符串原型对应的push等属性,所以array为对象

合并、切割、复制数组

合并数组

  • 拼接 f08d2575a07bf03f350c354cca9ec58.png
    arr3.concat(arr4):调用arr3的concat属性,以自身为基础,在后面拼接出一个新的数组,原来的arr3,arr4数组没有变化

切割(截取)数组

arr1.slice(n) 从第n个元素开始截取,原数组不变

c73ce11c315cb58611afaab299a93d8.png

拷贝 (从0开始截取)

760ba6e6ea627b3b274770dd340e73c.png
多用于拷贝一个数组

  • 注意 JS只提供浅拷贝

元素的增删改查

删元素

  • delete arr[i](第i个)

cf1eb7c99b8c5e5ec752a02848254ce.png
删除第0个字符串'a',字符串长度不变,原有的项目还存在,只是空的,arr即为稀疏数组

  • 改数组长度

6709ce59d2bb3b0b2641e9ce97376e1.png
数组长度为5,改变length属性,长度变为1,仅剩下1。因此不要随便改length,某些情况下影响数组的调用

  • 删除头部元素

1632194887(1).png arr被修改,并返回被删元素

  • 删除尾部元素

1632194994(1).png arr被修改,并返回删除元素5

  • 删除中间的元素 arr.splice(index,n,'x','y')
  1. index:从第几个开始删(取值0,1,2,3,4)
  2. n:删几个
  3. 'x','y':加上什么,可写多个

查看所有元素

查看所有属性名

  • Object.keys(arr)和for循环法 例声明一个数组[1,2,3,4],其中另外加入key:xxx,value为x a0a31c88967329637b382d42d83623e.png
    Object法,直接输出了所有key,即0,1,2,3,4,x
    for循环,直接输出每个key和对应的value
    这两种方法都是输出后面添加的xxx属性,存在局限性
  • for each
  1. 循环法

308e8c066c4a34d97974b601d788dd4.png 引入变量i,控制条件为length-1,等于length终止,所以调用keys的时候只能调用数字形式,避开了x

  • forEach调用函数

88017a935655cd9f188bb127b03e41d.png 调用forEach原型上的函数,item为value对应参数,index为key对应参数,两个参数名字可以随便取

forEach原理

  • forEach用for访问array的每一项
  • 对每一项调用fn(array[i],i,array)
  • 为什么要传入array? 规定如此 1c74c44a1d14c9227a93c9a9b7ad150.png

查看单个属性

跟对象一样

a7dbda467e7692658d5272dff90c227.png

索引越界

7b5396d0e49aff125b1bb4bc568de78.png
此时arr[arr.length]等价于arr[4],数组下标从0-3,不存在4,所以返回undefined

8059d70e7e874905485a1521b613659.png
同理,数组不存在下标-1,所以返回undefined

  • 举例证明

1632213550(1).png 最后一次循环报错,i等于length,超出下标,反之,去掉= 号,代码不报错

查找某个元素是否在数组里

  • arry。indexOf(item) 存在返回索引,否则返回-1

1632224383(1).png以上案例显示两种方法:

  1. 循环遍历,方法较为基础,繁琐
  2. arry.indexOf(item),固定写法,括号内为所要查找的元素,存在,返回顺序值,不存在返回-1

使用条件查找元素

  • arr.find(item=> %2===0) 找到第一个偶数

1632225325(1).png

  • arr.findIndex(item=>item%2==0) 找到第一个偶数的索引

1632225421(1).png

增加数组中的元素

在尾部添加元素

  • arr.push(newItem) 修改原来数组,返回新长度,newItem可写多个

在头部添加元素

  • arr.unshift(newItem) 用法同上

在中间添加元素

  • arr.splice(地址,删几个(取0一个都不删),新增内容)新增的内容可以写多个

修改数组中的元素

反转顺序

  • arr.reverse() 修改了原来的数组

1632226026(1).png

小应用

  • 如何反转字符串abcde

9c3ba29bd12ca6952515b814356e34a.png
思路: s不能直接反转,先转成数组,数组反转,再讲数组拼接成字符串

自定义顺序

  • arr.sort() 默认从小到大排列

1632228873(1).png

  • 按数值从小到大排列(同上效果)

2dbbfab57621d4d781e93628147fcbf.png

  • 按数值从大到小(多用于排名)比如成绩排名

2dbbfab57621d4d781e93628147fcbf.png

小应用

把对象进行排序

c9a1bb60fde10b752f62625eded6bab.png
思路:sort引用函数,将每个对象类比成单个元素,元素再调用score,再用return:1/-1/0进行判断
简写:原理类似于return, 隐含着逻辑:二者相减 a>b返回正数,a===b返回0,a<b返回负数 如果按照成绩排名排,那么b的score减去a的 515e24f96f5339fba68d66f0b235cd9.png

1632230389(1).png

数组变换

抽象概览(以下三种操作不会改变原数组)

33813289b9321678031937aee3cbc6a.png

1.map(应用场景:数组元素逐个变换)

71fc12ad747c2613feb8718bcab22c0.png数组各个元素变成平方,参数item可任意取名

2.filter(应用场景:特定条件筛选功能)

b69457780e5a7cc01768eb7f00b18f1.png 提取偶数

3.reduce(应用场景:对数组进行变换,转化为不同形式的对象,灵活多变)

d5228508262899ad554edb671b05b12.png
数组求和 ,参数 1:结果,数组元素 2:变化的规则 3:结果的初始值

reduce思想模型:上车打劫

1632232256(1).png
如图:小人手中的袋子为结果,其中的0为初始值,红色数字为数组各项值,红色箭头部分(将钱装入口袋的过程)为执行的操作

用reduce得到数组元素平方

3b05fcf81c09f39d49ca2d238d3b9dc.png 思路 传入参数result:返回的数组,初始值为[]空数组、参数item。调用concat,空数组与元素平方拼接,循环6次,得到元素平方的数组
逻辑图解

6ed0de6cf89d41a605af2b2e3aaa4e4.png

用reduce实现filter效果 例:筛选出偶数

37b539648e755a29313a28f7e2a83a2.png

002f01ba9c3592a6f9afd4109dc065f.png

  • 循环法思路:result为空数组,如果为基数,返回result,反之为偶数,调用concat将item放入result中,如此循环
  • 初次简化思路: 思想同上
  • 最终简化 思路:result初始值为[],直接一次性调用concat属性,属性内部加入判断语句。 如果item为奇数,result拼接空数组[](等价于什么都没加),如果判断为偶数,result拼接item 如此循环,得出数组

综合案例

f675c13630b16ed0b3c37c813b3511f.png

解题

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: [] })            初始化结果