JS学习笔记(八)
本系列更多文章,可以查看专栏 JS学习笔记
文章目录
- JS学习笔记(八)
- 一、数组(Array)
- 二、数组元素
- 三、常见的数组方法
- 1. 非破坏性方法(不改变原数组)
- (1)Array.isArray()
- (2)Array.prototype.at(i)
- (3)Array.prototype.concat()
- (4)Array.prototype.indexOf()
- (5)Array.prototype.lastIndexOf()
- (6)Array.prototype.join()
- (7)Array.prototype.slice()
- (8)Array.prototype.filter()【高阶函数】
- (9)Array.prototype.map()【高阶函数】
- (10)Array.prototype.reduce()【高阶函数】
- (11)Array.prototype.every()【高阶函数】
- (12)Array.prototype.some()【高阶函数】
- (13)Array.prototype.includes()
- 2. 破坏性方法(会改变原数组)
- (1)Array.prototype.push()【栈方法,LIFO后进先出】
- (2)Array.prototype.pop()【栈方法,LIFO后进先出】
- (3)Array.prototype.unshift()【队列方法,FIFO先进先出】
- (4)Array.prototype.shift()【队列方法,FIFO先进先出】
- (5)Array.prototype.splice()
- (6)Array.prototype.reverse()
- (7)Array.prototype.sort()【高阶函数】
- (8)Array.prototype.fill()
- (9)Array.prototype.copyWithin()
- 结尾
一、数组(Array)
数组类型是引用数据类型之一。
1. 创建数组语法
数组Array类型是一种可变值,原始类型(Number、BigInt、String、Boolean、Null、Undefined、Symbol)是不可变值。
方式1:使用Array创建空数组
let arr = new Array();
方式2:使用字面量创建空数组
let arr = [];
方式3:使用字面量创建数组,并添加元素值
语法: let 数组名 = [元素1,元素2……];
元素可以为任意数据类型,不过实际使用中,数组中元素类型具有一致性
let arr = [1, 3, 5, 7, 9];
2. 创建数组方法 【ES6新增】
- ①
Array.from()
:将类数组结构转换为数组实例
- 第一个参数:一个类数组对象,即任何可迭代的结构,或者有一个
length
属性和可索引元素的结构。- 第二个参数:接受可选的映射函数参数,直接增强新数组的值,无需使用Array.from().map()
- 第三个参数:指定映射函数中
this
的值- ②
Array.of()
:将一组参数转换为数组实例
// 传入arguments类数组对象
function test(a, b, c, d) {
// arguments是类数组
console.log(arguments); // Arguments(4) [1, '2', 'c', 4, callee: ƒ, Symbol(Symbol.iterator): ƒ]
console.log(Array.from(arguments)); // [1, '2', 'c', 4]
console.log(Array.of(a, b, c, d)); // [1, '2', 'c', 4]
}
test(1, "2", "c", 4);
二、数组元素
1. 添加 / 修改数组元素方法
方式1:使用 []添加元素,并为元素赋值或修改指定索引处的元素值
语法: 数组名[索引] = 元素值;
const arr = [];
arr[5] = 6;
代码实际运行效果,如下图所示:
分析:1. 数组的索引从0开始计数,arr[5]添加的实际上是第六个位置
2. 若从随机索引位添加元素,从arr[0]至新增元素之间,没有指定值的位置均为空元素
3. 数组中的对象存储在一片区域,且地址为连续的值,故通常实际使用时,会按索引顺序进行赋值,尽量减少非必要的空元素
方式2:始终为数组末尾添加元素
length是Array的一个实例属性,Array.prototype.length
始终返回数组的长度
语法: 数组名[数组名.length] = 元素值;
const arr = [1, 3, 5, 7, ,];
console.log("arr", arr); // [1, 3, 5, 7, 空白]
arr[arr.length] = 11;
console.log("arr", arr); // [1, 3, 5, 7, 空白, 11]
2. 遍历数组
const arr = [1, 3, 5];
(1)for循环
console.log("从头开始遍历");
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
console.log("从末尾开始遍历");
for (let i = arr.length - 1; i >= 0; i--) {
console.log(arr[i]);
}
示例代码运行效果,如下图所示:
(2)for…of…循环
从 arr
的起始索引逐个获取(仅能从起始位置),of
前面定义的变量用于存储每次获取的元素
注:此方法,可以用于遍历任何 可迭代对象
for (let value of arr) {
console.log(value);
}
// 只要是可迭代对象,均可遍历
for (let ch of "hello") {
console.log(ch);
}
(3)Array.prototype.forEach()方法
回调函数指,以函数B作为函数A的参数,并在函数A内部调用函数B
注:1. 参数为一个指定的回调函数,且该回调函数有三个参数
2. 第一个参数为 数组元素
,常定义为 element
;第二个参数为 数组索引
,常定义为 index
;第三个参数为 当前数组
,常定义为array
const arr = ["张三", "李四", "王五"];
// 三个参数时
arr.forEach((element, index, array) => {
console.log(element, index, array);
});
// 两个参数时
arr.forEach((element, index) => {
console.log(element, index);
});
// 一个参数时
arr.forEach((element) => {
console.log(element);
});
如下图所示:
(4)迭代器方法
- ①
keys()
: 返回数组索引的迭代器- ②
values()
: 返回数组元素的迭代器- ③
entries()
: 返回数组索引/值对的迭代器
const arr = ["张三", "李四", "王五"];
// 将可迭代对象转换成数组实例
console.log(Array.from(arr.keys())); // [0, 1, 2]
console.log(Array.from(arr.values())); // ['张三', '李四', '王五']
console.log(Array.from(arr.entries())); // [[0, '张三'], [1, '李四'], [2, '王五']]
3. 多维数组
此部分内容参考 《JavaScript权威指南(第6版)(中文版)》
JS中实际上没有多维数组,但是可以为将数组作为数组元素进行添加,来达到多维数组的效果,即 嵌套数组
// 定义一个10*10数组 - 参考《JavaScript权威指南(第6版)(中文版)》
const table = new Array(10);
for (let i = 0; i < 10; i++) {
table[i] = new Array(10);
}
// 初始化九九乘法表
for (let row = 0; row < table.length; row++) {
for (let col = 0; col < table[i].length; col++) {
table[row][col] = row * col;
}
}
三、常见的数组方法
本文中所有方法的更多用法,或更多数组方法,可以参考 Array - JavaScript | MDN 进行学习。
1. 非破坏性方法(不改变原数组)
注:通常数组的部分方法,可以被类数组对象、字符串使用,但一般不可以使用破坏性方法(修改数组的方法)
类数组对象:通常为普通对象但是具有类似于数组的length的属性
(1)Array.isArray()
是静态方法,用于判断是否为数组,返回值为 true
或 false
console.log(Array.isArray("hello")); // false
console.log(Array.isArray(["hello"])); // true
(2)Array.prototype.at(i)
是实例方法,用于获取指定索引 i
处的元素
注:区别于使用 []
,本方法可以 i
指定负数,表示从末尾开始计数,-1
表示 倒数第一个索引
const arr = [1,3,5,7,5,8,7,9]
console.log(arr.at(3)); // 7
console.log(arr.at(-1)); // 9
(3)Array.prototype.concat()
是实例方法,用于将使用此方法的实例与括号内的数组拼接,并返回一个新数组
const arr1 = [1,3,5]
const arr2 = [2,4,6]
console.log("arr1.concat(arr2)",arr1.concat(arr2))
console.log("arr1",arr1)
console.log("arr2",arr2)
由下图可知,此方法会返回一个新数组,并不会修改原数组
(4)Array.prototype.indexOf()
是实例方法,用于获取指定元素第一次在数组中出现的索引;若无,返回 -1
const arr = [1,3,5,7,5,8,7,9]
console.log(arr.indexOf(5)) //2
(5)Array.prototype.lastIndexOf()
是实例方法,用于获取指定元素最后一次在数组中出现的索引;若无,返回 -1
const arr = [1,3,5,7,5,8,7,9]
console.log(arr.lastIndexOf(5)) // 4
(6)Array.prototype.join()
是实例方法,用于将一个数组,转换为字符串,默认以逗号分隔;可以指定连接符,也可以省略
const arr = [11,22,33,44,55]
console.log(arr.join()) // 11,22,33,44,55
console.log(arr.join("+")) // 11+22+33+44+55
(7)Array.prototype.slice()
是实例方法,用于截取数组,但不会改变原数组
注:1. 不指定参数时,默认截取全部数组,相当于浅拷贝数组
2. 指定一个参数时,即默认截取从指定索引处至末尾
3. 指定两个参数时,即截取第一个位置截取到第二个位置的前一个位置(即含第一个,不含第二个)
const arr = [11,22,33,44,55]
console.log(arr.slice()) // [11,22,33,44,55]
console.log(arr.slice(3)) // [44,55]
console.log(arr.slice(1,3)) // [22,33]
(8)Array.prototype.filter()【高阶函数】
是实例方法,用于筛选数组中符合条件的元素,将其保存至新数组,并返回新数组
注:1. 参数为一个指定的回调函数,且该回调函数有三个参数
2. 第一个参数为 数组元素
,常定义为 element
;第二个参数为 数组索引
,常定义为 index
;第三个参数为 当前数组
,常定义为array
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// 保留大于5的元素
console.log(arr.filter((ele) => ele > 5));
// 保留偶数
console.log(arr.filter((ele) => ele % 2 === 0));
// 查看原数组
console.log(arr);
如下图所示:
(9)Array.prototype.map()【高阶函数】
是实例方法,用于对当前数组进行指定操作,得到一个新数组
注:1. 参数为回调函数,且同filter()方法
2. 回调函数的返回值,将构成新数组
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
console.log(arr.map((ele) => ele * 3));
console.log(arr.map((ele) => ele ** 3));
console.log(arr.map((ele) => ""));
如下图所示:
(10)Array.prototype.reduce()【高阶函数】
是实例方法,用于将当前数组进行整合,返回一个值
注:1. 参数为回调函数
2. 第一个参数,为数组第一个值或前一次操作的值;第二个参数,为当前元素的值
const arr = [1, 2, 3, 4, 5];
// 求所有元素的和,pre=1,cur=2; pre=3,cur=3; pre=6,cur=4...
console.log(arr.reduce((pre, cur) => pre + cur)); // 15
// 求所有元素的乘积
console.log(arr.reduce((pre, cur) => pre * cur)); // 120
(11)Array.prototype.every()【高阶函数】
是实例方法,用于判断所有元素,是否满足回调函数返回值条件;若均为true,则最终结果为true;否则为false
注:1. 参数为回调函数
2. 第一个参数,为数组第一个值或前一次操作的值;第二个参数,为当前元素的值;第三个参数,为当前数组
const arr = [1, 2, 3, 4, 5];
// 判断数组所有元素是否都小于5
console.log(arr.every((ele) => ele < 5)); // false
// 判断数组所有元素是否都小于等于5
console.log(arr.every((ele) => ele <= 5)); // true
(12)Array.prototype.some()【高阶函数】
是实例方法,用于判断任一元素,是否满足回调函数返回值条件;若有一个元素为true,则最终结果为true;当所有结果为false时,最终结果为false
注:1. 参数为回调函数
2. 第一个参数,为数组第一个值或前一次操作的值;第二个参数,为当前元素的值;第三个参数,为当前数组
const arr = [1, 2, 3, 4, 5];
// 判断数组所有元素中是否存在
console.log(arr.some((ele) => ele >= 5)); // true
(13)Array.prototype.includes()
是实例方法,用于从数组第一项开始向后搜索,返回值表示是否至少找到一个与指定元素匹配的项
2. 破坏性方法(会改变原数组)
(1)Array.prototype.push()【栈方法,LIFO后进先出】
是实例方法,用于向数组末尾添加一个或多个元素,并返回数组当前的长度
const arr = ["张三", "李四"];
console.log(arr.push("王五", "老六")); // 4
console.log(arr); // ['张三', '李四', '王五', '老六']
(2)Array.prototype.pop()【栈方法,LIFO后进先出】
是实例方法,用于删除末尾最后一个元素,并返回被删除的元素
const arr = ["张三", "李四", "王五", "老六"];
console.log(arr.pop()); // 老六
console.log(arr); // ['张三', '李四', '王五']
(3)Array.prototype.unshift()【队列方法,FIFO先进先出】
是实例方法,用于向数组第一个元素之前添加一个或多个元素,并返回数组当前的长度
const arr = ["张三", "李四"];
console.log(arr.unshift("王五", "老六")); // 4
console.log(arr); // ['王五', '老六', '张三', '李四']
(4)Array.prototype.shift()【队列方法,FIFO先进先出】
是实例方法,用于删除第一个元素,并返回被删除的元素
const arr = ["王五", "老六", "张三", "李四"];
console.log(arr.shift()); // 老六
console.log(arr); // ['老六', '张三', '李四']
(5)Array.prototype.splice()
是实例方法,用于 删除、插入、替换元素
- 参数1: 起始索引位置
- 参数2: 删除元素个数
- 参数3: 要插入的元素
- 返回值: 被删除的元素
const arr = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4];
// 仅删除元素 [仅使用2个参数]
console.log(arr.splice(2, 3)); // [2, 3, 3]
console.log(arr); // [1, 2, 3, 4, 4, 4, 4]
// 替换单个元素 [使用3个参数]
console.log(arr.splice(4, 1, 10)); // [4]
console.log(arr); // [1, 2, 3, 4, 10, 4, 4]
// 插入元素 [使用3个参数]
console.log(arr.splice(5, 2, "哈哈", "呵呵")); // [4, 4]
console.log(arr); // [1, 2, 3, 4, 10, '哈哈', '呵呵']
(6)Array.prototype.reverse()
是实例方法,用于将当前数组倒序排序,返回值则为当前数组
const arr = ["张三", "李四", "王五", "老六"];
console.log(arr.reverse()); // ['老六', '王五', '李四', '张三']
console.log(arr); // ['老六', '王五', '李四', '张三']
(7)Array.prototype.sort()【高阶函数】
是实例方法,用于对数组排序,默认以Unicode编码属性排序;也可以指定排序规则
- 第一个参数
a
和第二个参数b
- 升序:
a - b < 0
;a
在b
前面- 降序:
a - b > 0
;b
在a
前面- 相等: 差值为0
const arr = [5, 1, 3, 7, 9, 6, 5];
// 不指定参数
console.log(arr.sort()); // [1, 3, 5, 5, 6, 7, 9]
// 指定回调函数
console.log(arr.sort((a, b) => a - b)); // 升序排列,[1, 3, 5, 5, 6, 7, 9]
console.log(arr.sort((a, b) => b - a)); // 降序排列, [9, 7, 6, 5, 5, 3, 1]
(8)Array.prototype.fill()
是实例方法,用于 填充数组,不会改变数组的长度。
- 参数1: 填充值
- 参数2: 可选开始索引值,默认是起始位置(负索引值,相当于总长度与负索引值的和)
- 参数3: 可选结束索引值,默认一直填充到数组末尾;若有结束索引值,则不包含结束索引值本身(负索引值,相当于总长度与负索引值的和)
const arr = new Array(5);
// 从第0个填充到末尾
arr.fill(3);
console.log(arr);
// 从第(-3+5)=2个填充到末尾
arr.fill(4, -3);
console.log(arr);
// 从第(-5+5)=0个填充到第3个(不含第4个)
arr.fill(6, -5, 4);
console.log(arr);
(9)Array.prototype.copyWithin()
是实例方法,会按照指定范围浅复制数组中的部分内容,然后将它们插入到指定索引开始的位置不会改变数组的长度。
- 参数1: 指定插入的开始索引值
- 参数2: 可选开始索引值,默认是起始位置(负索引值,相当于总长度与负索引值的和)
- 参数3: 可选结束索引值,默认一直填充到数组末尾;若有结束索引值,则不包含结束索引值本身(负索引值,相当于总长度与负索引值的和)
const arr = [0, 1, 2, 3, 4];
// 将数组第1个元素到末尾元素插入到第3个位置,且不改变数组长度
arr.copyWithin(3);
console.log(arr); // [0, 1, 2, 0, 1]
// 将数组第(-3+5)=2个元素到末尾元素插入到第4个位置,且不改变数组长度
arr.copyWithin(4, -3);
console.log(arr); // [0, 1, 2, 0, 2]
// 从第(-4+5)=1个到第4个(不含第4个)元素插入到第1个位置
arr.copyWithin(1, -4, 4);
console.log(arr); // [0, 1, 2, 0, 2]
结尾
部分内容参考《ECMAScript 6 入门》《JavaScript权威指南》《JavaScript高级程序设计》,如有错误,欢迎评论区指正。