什么是数组?
内存中连续存储多个数据的存储空间,再起一个名字。(一组连续的变量的集合)
为什么会有数组?
程序=数据结构+算法
数据结构: 数据在内存中的存储结构
算法: 解决一个问题的步骤
良好的数据结构可以极大提高程序的执行效率
何时使用数组?
今后,只要保存多个相关的数据,都要用数组。
如何创建数组?
1. 创建空数组:
var arr=[];//创建一个新数组的意思
var arr=new Array();
2. 创建数组同时,初始化数组元素:
var arr=[值1,值2,...];
var arr=new Array(值1,值2,...);
3. 创建n个空元素的数组:
var arr=new Array(n);
如何对数组赋值/取值(都要用下标):
- 下标: 数组中唯一标识一个元素的序号
- 自动分配的数字下标:
- 从0开始,递增,连续不重复
赋值: arr[i]=值;
- 特殊: 如果arr中i位置没有元素,会自动创建新元素。
- 稀疏数组: 下标不连续的数组
取值: 数组中每个元素的用法和普通变量完全一样!
如果访问数组中一个不存在的下标位置,不会报错,会返回undefined!
vs 其他语言中的数组: 3不限制:
属性: arr.length: 表示数组中理论上的元素个数。
arr.length始终等于最后一个元素的下标+1
固定套路:
1.获得最后一个元素: arr[arr.length-1]
2.获得倒数第n个元素: arr[arr.length-n]
3.末尾追加: arr[arr.length]=值
4.缩容: arr.length-=n,减小数组容量
超出的元素会丢弃
比如: 删除最后一个元素:
arr.length-=1
数组是引用类型的对象:
垃圾回收: js引擎会自动释放不再被任何变量引用的对象。
垃圾回收器: js引擎中的小程序,专门负责记录内存中对象的引用次数,并删除不再被引用的对象。
伴随主线程在后台自动执行。
建议: 今后只要使用完较大的对象,都要主动赋值为null,释放对对象的引用。
当所有变量都释放对一个对象的引用后,对象被垃圾回收。
遍历索引数组:
- 不限制元素个数
- 不限制元素的数据类型
- 不限制下标越界
for(var i=0;i<arr.length;i++){
arr[i]//当前元素
}
索引数组: 下标为数字的数组都是索引数组
关联数组(hash数组):
什么是: 可自定义下标名称的数组
为什么: 索引数组中的下标是无意义的数字
[林心如, 81, 56, 86]
name math chs eng
var lxr=[];
lxr["name"]="林心如";
lxr["math"]=81;
lxr["chs"]=56;
lxr["eng"]=86;
console.dir(lxr);
console.log(lxr["math"]);
//输出lxr的所有个人信息:
for(var key in lxr){
console.log(key+":"+lxr[key]);
}
何时: 只要希望每个元素有明确的意义时
如何创建: 2步:
1. 创建空数组: var lxr=[];
2. 向空数组中添加元素,为每个元素定义元素名。
lxr["name"]="林心如"
取值/赋值: 每个元素的取值和赋值和索引数组的用法完全相同。只不过下标变为有意义的名称字符串。
强调: 关联数组中length属性失效!
遍历关联数组: for in循环
for(var key in arr){
arr[key]//当前元素
}
in: 依次取出arr中每个元素的下标名称,保存在变量key中
hash数组的原理:
- hash算法: 专门接收一个字符串,计算出一个尽量不重复的序号。
- 相同字符串,先后计算出的序号一定相同
- 存储: 根据元素的名称,计算出一个序号
- 将元素值保存到指定序号的位置上
取值/查找: 用提供的元素名,计算出和存储时完全相同的序号,直接到序号所在位置获取元素值。
优: 查找速度极快:
- 不用遍历,查找速度和元素个数,以及存储位置无关!
- vs 索引数组: 只能靠遍历查找,查找速度慢,受元素个数和元素存储位置的影响极大。
数组常用API:
1. 转字符串:
String(arr): 将每个元素都转为字符串,用","相连。——拍照 用于判断数组是否发生变化
var str=arr.join("连接符"):
将每个元素都转为字符串,用自定义的"连接符"相连。
固定套路:
2. 无缝拼接: arr.join("")
如果省略"",就和String等效了
2. 将单词拼接成句子:
arr.join(" ")
3. 将数组元素,批量生成页面元素:
"<标签>"+
arr.join("</标签><标签>")+
"</标签>"
3.连接和截取子数组:
连接: var newArr=arr1.concat(arr2);
将arr2拼接到arr1之后,返回新数组
强调: concat无权修改原数组,只能返回新数组,必须用变量接住拼接的结果。
其实: .concat(值1,值2,arr2,....);
其中: .concat可以打散数组类型的参数为单个值。
截取子数组:
var subArr=arr.slice(starti,endi+1);
截取arr中starti位置开始到endi位置结束的子数组。
强调: 也无权修改原数组,只会复制子数组。
强调: API中同时出现开始位置和结束位置时,都是含头不含尾。
变化: 1. 省略第二个参数,表示截取到结尾。
4.颠倒数组元素: arr.reverse();
直接修改原数组。
5.splice: 删除,插入,替换
删除: arr.splice(starti,n)
删除arr中starti位置开始的n个元素
强调: n是个数,不考虑含头不含尾
其实splice可返回删除的元素组成的临时数组。
var deletes=arr.splice(starti,n)
插入: arr.splice(starti,0,值1,值2,...)
在arr的starti位置插入值1,值2,...
原starti位置及其之后的值,都被向后顺
移
强调: 0 表示不删除,只插入新值
不支持打散数组类型参数。
如果传入数组,会形成子数组
vs concat:
concat: 优: 打散数组类型参数
缺: 只能拼接在开头或结尾
splice: 优: 可指定插入位置
缺: 不支持打散数组参数
替换: var deletes=
arr.splice(starti,n,值1,值2,...)
先删除starti位置开始的n个,再在starti位置插入值1,值2。
强调: 删除的元素个数,和插入新值得个数,不必一致。
6:arr.sort:
自定义: 冒泡,(快速,插入)——手写
原理:
API: arr.sort();
将arr中的元素按升序排列
问题: 默认将所有元素转换为字符串再排列
为什么: js中的数组不限制元素的类型
为了保证sort方法正常执行,默认将所有元素转为字符串,再比较unicode。
所以,默认的sort方法,只能排序字符串元素
如果排序非字符串类型的元素: 2步
1. 自定义比较器函数
比较器函数: 专门比较两个值大小的函数
如何定义:
参数: a,b 分别接收要比较的两个值
返回值: 如果a>b,就返回正数
否则,如果a<b,就返回负数
否则,就返回0
专门比较两个数字大小的比较器:
function compare(a,b){
return a-b;
}
专门比较两个字符串长度的比较器:
function compare(a,b){
return a.length-b.length;
}
2. 将比较器函数传入sort方法作为比较大小的依据。
arr.sort(compare);
补: 其实,函数有第二种创建方法:
var 函数名=function(...){...}
何时使用: 只要不希望被声明提前时
vs function 函数名(...){...}
只有一点差别:
function 函数名 会被声明提前,
var 函数名=function 不会被声明提前
降序: 颠倒比较器的正负号,可改升序为降序。
7.栈(stack)和队列(queue):
js中没有专门的栈和队列的类型。
都是用普通的数组模拟
只不过调用了专门的API,按一定顺序操作数组的元素。
栈: 一端封闭,另一端进出的数组
FILO
只要希望始终使用最新进入数组的元素时
如何使用:
1. 结尾出入栈:
入: arr.push(值)
出: var last=arr.pop();
特点: 无论出入栈操作,剩余元素的位置不会发生变化。
2. 开头出入栈:
入: arr.unshift(值)
出: var first=arr.shift()
特点: 每次出入栈操作,剩余元素的位置都会受影响。
队列: 只能从一端进入,从另一端出的数组
FIFO
只要希望按照先来后到的顺序依次使用数组元素时
如何使用:
结尾入: arr.push(值)
开头出: var first=arr.shift()
二维数组: 数组中的元素,又引用了另一个子数组。
何时使用:
1.保存横行竖列的二维数据时
2.需要对现有数组内容,做进一步分类时
如何使用:
创建:
1. 创建空数组,后初始化:
var arr=[];
arr[0]=[...]
2. 创建数组同时,初始化元素:
var arr=[
[...],
[...],
...
]
访问二维数组的元素:
arr[r][c]
强调: 二维数组中r不能越界
遍历二维数组:
for(var r=0;r<arr.length;r++){
for(var c=0;c<arr[r].length;c++){
arr[r][c]//当前元素
}
}