一、数组的定义和基本使用
1. 数组简介和定义
数组(Array),顾名思义,用来
存储一组相关的值
,从而方便进行求和、计算平均数、逐项遍历等操作。jsvar scoreArr = [96, 07, 76, 87, 100];
数组是非常重要的一种
数据结构
。数组的定义
jsvar arr = ['A', 'B', 'C']; // 或者 var arr = new Array('A', 'B', 'C'); // 或者 但是值都是 undefined var arr = new Array(4);
访问数组项
- 数组每一项都有下标,下标从0开始
- 可以使用
方括号中书写下标
的形式,访问数组的任一项。
下标越界
- JavaScript规定,
访问数组中不存在的项会返回undefined
,不会报错。
- JavaScript规定,
数组的长度
- 数组的
length
属性表示它的长度 - 数组最后一项的下标是数组的长度减1
- 数组的
更改数组项
- 如果更改的数组项超过了length-1,则会创造这项。
数组的遍历
- 数组的最大的优点就是方便遍历
2. 数组类型的检测
- 数组用
typeof
检测结果是object
。 Array.isArray()
方法可以用来检测数组。
二、 数组的常用方法
1. 数组的头尾操作
方法 | 功能 |
---|---|
push() | 在尾部插入新项 |
pop() | 在尾部删除 |
unshift() | 在头部插入新项 |
shift() | 在头部删除 |
push()
方法push()
方法用来在数组末尾推入新项
,参数就是推入的项。- 如果要推入多项,可以用逗号隔开。
- 调用
push()
方法后,数组会立即改变,不需要赋值。
pop
方法- 与
push()
方法相反,pop()
方法用来删除数组中的最后一项
pop()
方法不仅会删除数组末项,而且会返回被删除的项。
- 与
unshift()
方法unshift()
方法用来在数组头尾插入新项
,参数就是要插入的项。- 如果要插入多项,可以用逗号隔开。
- 调用
unshift()
方法后,数组会立即改变,不需要赋值。
shift()
方法- 与
unshift()
相反,shift()
方法用来删除数组中下标为0的项
shift()
方法不仅会删除数组首项,而且会返回被删除的项。
- 与
2. 数组的常用方法:splice
slice
splice()
方法splice()
方法用于替换数组中的指定项
jsvar arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G']; arr.splice(3, 2, 'X', 'Y', Z); console.log(arr); // ['A', 'B', 'C', 'X', 'Y', 'Z', 'F', 'G']
splice()
方法用于在指定位置插入新项
jsvar arr = ['A', 'B', 'C', 'D']; arr.splice(2, 0, 'X', 'Y', 'Z'); console.log(arr); // ['A', 'B', 'X', 'Y', 'Z', 'C', 'D']
splice()
方法可以用于删除指定项
jsvar arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G']; arr.splice(2, 4); // 没有设置替换的新项,仅删除4项 console.log(arr); // ['A', 'B', 'G']
splice()
方法会以数组形式返回被删除的项
slice()
方法slice()
方法用于得到子数组
slice(a, b)
截取的子数组`从下标为a的项开始,到下标为b(但不包括下标为b的项)结束slice(a, b)
方法不会更改原有数组。slice()
如果不提供第二个参数,则表示从指定项开始,提取所有后续所有项作为子数组
slice()
的参数允许为负数,表示数组的倒数第几项
3. 数组的常用方法:join
split
concat
reverse
indexOf
includes
join()
的参数表示以什么字符作为连接符
,如果留空则默认以逗号分割
,如同调用toString()
方法split()
的参数表示以什么字符拆分字符串
,一般不能留空。concat()
方法concat()
方法可以合并连结多个数组
。concat()
方法不会改变原数组。
reverse()
方法用来将一个数组中的全部项顺序置反。indexOf()
和includes()
方法indexOf()
方法的功能是搜索数组中的元素
,并返回它所在的位置,如果元素不存在,则返回-1includes()
方法的功能是判断一个数组是否包含一个指定的值
,返回布尔值。
三、数组算法
1. 遍历相关算法
- 求数组中每一项的总和、平均数js
// 求数组的总和和平均数 var arr = [3, 5, 3, 2, 1, 1]; // 累加器 var sum = 0; // 遍历数组,每遍历一个数字,就要把这个数字累加到累加器中 for (var i = 0; i < arr.length; i++) { sum += arr[i]; } console.log(sum); console.log(sum / arr.length);
- 求数组项的最大值和最小值js
// 求数组的最大值和最小值 var arr = [3, 4, 88, 3, 1]; // 定义两个变量,max表示当前寻找到的最大值,默认是arr[0] // min表示当前寻找到的最小值,默认是arr[0] var max = arr[0]; var min = arr[0]; // 遍历数组,从下标为1的项开始遍历 for (var i = 1; i < arr.length; i++) { // 如果你遍历的这项,比当前最大值大,那么就让当前最大值成为这个项 if (arr[i] > max) { max = arr[i]; } else if (arr[i] < min) { // 否则如果你遍历的这项,比当前最小值小,那么就让当前最小值成为这个项 min = arr[i]; } } console.log(max, min);
2. 数组去重和随机样本
- 去掉数组中的重复项
- 思路:准备一个空结果数组,遍历原数组,如果遍历到的项不在结果数组中,则推入结果数组。js
var arr = [1, 1, 1, 2, 2, 3, 3, 3, 2, 1]; // 结果数组 var result = []; // 遍历原数组 for (var i = 0; i < arr.length; i++) { // 判断遍历到的这项是否在结果数组中,如果不在就推入 // includes方法用来判断某项是否在数组中 if (!result.includes(arr[i])) { result.push(arr[i]); } } console.log(result);
- 思路:准备一个空结果数组,遍历原数组,如果遍历到的项不在结果数组中,则推入结果数组。
- 请随机从原数组中取3项
- 思路:准备一个空结果数组,遍历原数组,随机选择一项,推入结果数组,并且将这项删除。js
var arr = [3, 6, 10, 5, 8, 9]; // 结果数组 var result = []; // 遍历原数组 for (var i = 0; i < 3; i++) { // 随机选择一项的下标,数组的下表0~arr.length - 1; // 之前学习过一个random的公式,[a,b]区间的随机数是parseInt(Math.random() * (b-a+1)) + a; var n = parseInt(Math.random() * arr.length); // 把这项推入结果数组 result.push(arr[n]); // 删除这项,防止重复被随机到 arr.splice(n, 1); } console.log(result);
- 思路:准备一个空结果数组,遍历原数组,随机选择一项,推入结果数组,并且将这项删除。
3. 冒泡排序
- 冒泡排序的核心思路是
一趟一趟地进行多次项的两两比较
,每次都会将最小的元素排好位置,如同水中的气泡上浮一样。 4
个数字,共需要比较3趟,比较次数为3 + 2 + 1 = 6
次n
个数字,共需要比较n-1
趟,比较次数为n(n-1)/2
次js// 冒泡排序 var arr = [6, 2, 9, 3, 8, 1, 45, 23, 45, 49]; // 一趟一趟比较,趟数序号就是i for (var i = 1; i < arr.length; i++) { // 内层循环负责两两比较 for (var j = arr.length - 1; j >= i; j--) { // 判断项的大小 if (arr[j] < arr[j - 1]) { // 这一项比前一项还小了,那么就要交换两个变量的位置 var temp = arr[j]; arr[j] = arr[j - 1]; arr[j - 1] = temp; } } console.log(arr); } console.log(arr);
4. 二维数组
- 二维数组:以数组作为数组元素的数组,即"数组的数组"。
- 二维数组可以看做是矩阵。js
var matrix = [ [11, 33, 55], [22, 33, 44], [36, 49, 52], [56, 10, 23] ]; console.log(matrix.length); // 4 // 循环输出二维数组中的每一个项 for (var i = 0; i < 4; i++) { for (var j = 0; j < 3; j++) { console.log(matrix[i][j]); } }
4. 引用类型
- 相等判断时的区别
- 基本类型进行相等判断时,会比较值是否相等
- 引用类型进行相等判断时,会比较址是否相等,也就是说它会比较是否为内存中的同一个东西。
- 总结
举例 当var a = b变量传值时 当用 == 比较时 基本类型值
数字型、字符串型、布尔型、undefined型 内存中产生新的副本 比较值是否相等 引用类型值
对象、数组 内存中不产生新的副本,而是让新变量指向同一个对象 比较内存地址是否相同,即比较是否是同一个对象
5. 深克隆和浅克隆
- 使用
arr1=arr2
的语法不会克隆数组 - 浅克隆:
只克隆数组的第一层
,如果是多维数组,或者数组中的项是其他引用类型值,则不克隆其它层。 - 深克隆:
克隆数组的所有层
,要使用递归
技术。jsvar arr1 = [1, 2, 3, 4, [6, 9, 4]]; // 结果数组 var result = []; // 遍历原数组中的每一项,把遍历到的项推入到结果数组中 for (var i = 0; i < arr1.length; i++) { result.push(arr1[i]); } console.log(result); console.log(result == arr1); // 期望false,因为引用类型值进行比较的时候,等等比较的是内存地址 console.log(result[4] == arr1[4]); // 藕断丝连
6. 重点内容
- 数组是什么?应该如何定义?
- 如何检测数组类型?
- 数组有哪些常用方法?
- 数组的遍历相关算法、去重和随机样本、冒泡排序?
- 基本类型值和引用类型值的区别
- 实现浅克隆