1. 关联数组
- 索引数组: 下标为数字的数组
1.1. 关联数组
可自定义下标名称的数组
-
为什么: 为了让每个元素都有一个专门的名称
-
好处: 1. 便于维护
- 便于查找
-
何时: 1. 希望每个元素都有专门的意义时
- 希望快速查找元素时
-
创建: 2 步
- 先创建空数组:
var ym=[]
- 向空数组中添加新元素, 要使用自定义的下标名称
- Ex:
ym["name"] = "杨幂"
,ym["math"] = 81
,ym["chs"] = 59
- 先创建空数组:
-
访问: 访问关联数组和访问索引数组完全一样
- 只不过要使用自定义的下标名称
-
注意: 关联数组中
length
属性失效, 永远等于 0 -> 因为关联数组中没有数字下标,length
无法 + 1
1.2. 遍历关联数组( hash 数组 )
-
语法:
for(var key in ym){ // in 依次取出 ym 中每个 key key // 当前房间号, 反复取出每个下标放在变量 key 中 ym[key] // 当前元素值 <!-- 强调: key 不能加引号, 因为每次循环都在变化 --> }
-
Ex: 一次性获得关联数组中所有的下标号
var ym = []; ym["name"] = "杨幂" ym["math"] = 81; ym["chs"] = 59; ym["eng"] = 89; var keys = []; var i = 0; for(keys[i++] in ym); console.log(keys); // [name, math, chs, eng]
1.3. 关联数组原理
- 问题: 索引数组, 无法提前预知元素的具体位置, 下标无法表示元素的意义
- 只能遍历查找: 受元素个数和元素存储位置影响
- 解决:
hash
算法 -> 内存中的一个小程序, 根据一个字符串, 计算出尽量不重复的一个序号- 相同的字符串计算出的序号一定相同
- 不同的字符串, 计算出的数字几乎不同的
- 向关联数组中保存元素: 将自定义下标名交给
hash
算法, 计算一个散列的位置序号 -> 将元素保存到序号指定位置 - 从关联数组中取值时: 将自定义下标名交给
hash
算法, 计算出和存入时完全相同的序号, 引擎直接去序号位置获得元素- 优: 不受存储位置和元素个数的影响
2. 数组API
API
: 浏览器厂商已经实现的方法, 开发人员直接调用
-
console.log(arr)
: 先输出dir
的结构, 刷新后变为String(arr)
-
仅输出内容, 不关心结构:
console.log(String(arr))
-
查看数组存储结构:
console.dir(arr)
注意:
dir
查看结果时, 不遵循先后执行的顺序
-
-
String(arr)
: 不改变原数组-
将
arr
中每个元素都转为字符串, 用逗号连接 -
何时: 给数组拍照, 用于比较操作前后数组是否发生了变化
-
-
arr.join('连接符')
: 不改变原数组-
将
arr
中每个元素都转为字符串, 用自定义的连接符连接元素 -
何时: 只要希望使用自定义字符串连接时
-
固定套路: 1. 把单词拼接为句子:
arr.join(" ")
-
无缝拼接:
- 错误:
arr.join()
-> 不加引号, 分隔符为空 -> 默认逗号连接 - 正确:
arr.join("")
- 重要用途: 判断数组是否为空
- 错误:
-
动态生成页面元素
<select id="sel"><!--innerHTML--></select> <script> var provs=["北京","河北","河南","山东"]; var html="<option>" + provs.join("</option><option>") + "</option>" //设置元素的HTML内容为html字符串 sel.innerHTML = html </script>
-
-
优化: 数组的拼接比字符串的拼接效率更高
-
建议: 今后凡是频繁的字符串拼接, 都要2步
- 先将要拼接的子字符串放入一个数组中
- 调用数组的
join
方法, 一次性生成结果字符串
-
-
拼接和选取: 都无权修改原数组, 只能返回新数组对象
-
拼接: 将其他数据或另一个数组,和当前数组拼接为新数组
-
如何:
var newArr = arr1.concat(值1, 值2, arr2, ...)
-
强调: 1. 不修改原数组,只返回新数组
- 可打散数组类型参数为单个数据, 再拼接 ->
concat
独有
- 可打散数组类型参数为单个数据, 再拼接 ->
-
-
选取: 复制原数组中指定开始位置到结束位置之间的元素, 组成新数组
-
如何:
var subArr = arr.slice(starti, endi+1)
-
强调: 如果一个函数两个参数都是下标时, 就会含头不含尾
-
简写:
- 如果位置离结尾近, 可用负数下标:
arr.length - n
-> 可简写为:-n
- 可省略第二个参数, 表示一直选取到结尾
- 两个参数都可省略, 完整复制一个数组
- 如果位置离结尾近, 可用负数下标:
-
-
-
修改数组:
arr.splice()
-
强调: 直接修改原数组
-
删除元素:
arr.splice(starti, n)
-
删除
starti
位置开始的 n 个元素 -
强调: 不必考虑含头不含尾
-
有返回值: 返回被删除的元素组成的临时数组 -> 若是删掉的不要, 不用赋值
var deletesArr = arr.splice(starti, n)
-
简写: 1. 省略 n, 表示当前删除到结尾
- 支持负数下标, 表示倒数第几个 -> 到结尾
-
-
插入新元素:
arr.splice(starti, 0, 值1, 值2,...)
-
在
starti
位置插入值1, 值2, ... -> 原starti
位置的值向后顺移 -
强调: 不支持打散数组参数
-
-
替换: 先删除旧的, 再在同一位置插入新的
-
语法:
arr.splice(starti, n, 值1, 值2,...)
-
先删除
starti
开始的 n 个元素 -> 再在starti
位置插入值1, 值2, ... -
强调: 删除的个数和插入的个数可以不相同
-
-
-
翻转:
arr.reverse()
- 颠倒数组中所有元素的位置, 直接改变原数组
-
排序:
-
什么是: 将数组中的元素按从小到大或从大到小的顺序重新排列
-
何时: 所有要给用户展示的数据必须都要先排序
-
如何:
arr.sort()
-
默认排序规则: 将所有元素都转为字符串, 再按字符串升序排列
-
何时: 只有按字符串升序排列时, 才用默认的
sort()
-
问题: 只能按字符串升序排列
-
解决: 自定义比较器函数
-
什么是: 专门比较任意两值大小的函数
-
要求: 2个参数
-
返回值: 1. 如果
a > b
, 就返回正数- 如果
a<b
, 就返回负数 - 否则返回0
- 如果
-
最简单的数字升序比较器:
function cmp(a, b){ return a - b;}
-
如何使用: 将比较器函数对象作为参数传入
sort()
函数中:arr.sort( cmp )
-
强调: 不加
()
-
回调: 自己定义的函数, 自己不调用 -> 而是传入另一个函数中, 被另一个函数反复调用
-
何时: 只要对数字元素排序, 都要自定义比较器函数
-
-
-
问题2: 如何降序
- 解决: 只要颠倒比较器结果的正负号, 就可改升序为降序
- 最简单的数字降序比较器:
function cmp(a, b){return b - a}
- 简写:
arr.sort(function(a, b){ return a - b })
- 简写:
-
-
-
-
栈和队列
-
说明:
JS
中没有专门的栈和队列结构, 都是用普通数组模拟的 -
栈
stack
-
什么是栈: 一端封闭, 只能从另一端进出的数组
-
何时: 只要希望始终使用最后进入数组的新元素时
-
如何:
-
结尾出入栈
-
结尾入栈:
arr.push(值)
=>arr[arr.length] = 值
-
强调: 1. 其实
push
可压入多个值- 不支持打散数组参数
-
-
结尾出栈:
var last = arr.pop()
-
-
开头出入栈:
-
开头入栈:
arr.unshift(值)
-
强调: 开头入栈后的元素顺序和结尾入栈后的元素顺序是相反的
-
-
开头出栈:
var first=arr.shift()
-
-
-
-
-
总结
- 向数组中添加元素 4 种
concat
: 1. 不修改原数组, 返回型数组 2. 在结尾拼接元素 3. 支持打散数组类型参数splice
: 1. 直接修改原数组 2. 在任意位置插入新元素 3. 不支持打散数组类型参数push
: 1. 直接修改原数组 2. 只能在结尾拼接元素 3. 不支持打散数组类型参数unshift
: 1. 直接修改原数组 2. 只能在开头拼接元素 3. 不支持打散数组类型参数
- 取出数组元素: 4 种
slice
: 1. 可以获取任意位置的任意个元素 2. 不修改原数组, 返回选中的元素组成的新数组splice
: 1. 删除任意位置的任意个元素 2. 直接修改原数组 3. 返回被删除的元素组成的新数组pop
: 1. 只能从结尾删除一个元素 2. 直接修改原数组 3. 返回被删除的元素shift
: 1. 只能从开头删除一个元素 2. 直接修改原数组 3. 返回被删除的元素
- 向数组中添加元素 4 种
-
队列(
queue
):- 什么是: 只能从结尾进入, 从开头出的数组
- 何时: 只要希望按照先来后到的顺序使用数组元素时
- 如何: 1. 从结尾入队列:
arr.push(值)
2. 从开头出队列:var first = arr.shift()
3. 二维数组
-
什么是: 数组中的元素, 又引用了另一个子数组
-
何时: 2种
- 保存横行竖列的二维数据
- 一个大的数组中, 还需要对元素进行更细致分类
-
如何:
-
创建: 2 种
-
先创建空数组, 再添加子数组
var arr = [] arr[0] = [0, 0, 0, 0] arr[1] = [0, 0, 0, 0]
-
创建数组同时, 初始化子数组
var arr = [ [0, 0, 0, 0], [0, 0, 0, 0] ]
-
-
-
访问:
arr[r][c]
每个元素的用法和普通数组的元素完全一样- 越界: 二维数组的行下标
r
, 不能越界
- 越界: 二维数组的行下标
-
遍历二维数组: 外层循环控制行, 内层循环控制列
for(var r = 0; r < arr.length; r++){ for(var c = 0; c < arr[r].length; c++) { arr[r][c] // 当前正在遍历的元素 } }