JavaScript高级程序设计(第5版):无处不在的集合

每个系列一本前端好书,帮你轻松学重点。

本系列来自曾供职于Google的知名前端技术专家马特·弗里斯比 编写的 《JavaScript高级程序设计》(第5版)

世界上很少有事物孤立存在,即便你是单身,世界上有很多单身...

所以,集合(列表)是一种很常见的数据形式,新闻列表、人员名单列表等。

本篇文介绍JavaScript中的这类数据。

集合的共性

你一眼就能看出什么样的数据是集合,就像这样:

复制代码
1,2,3,4,5
张三,李四,王五

所以必然存在共性,如:包含多个同类型的值(即便可以不同),能够遍历、增加、删除、查找、修改。

但往往因为集合类型的不同,适用场景也不同。

数组

数组是最常见的集合类型,不仅JavaScript,其他语言同样,但在JavaScript中,它有其特殊性,它的每个索引位可以存储不同类型的数据,而且是动态大小,会随着数据增加自动增长。

数组定义

定义数组有若干方法,以下都是可行的:

javascript 复制代码
let colors = new Array();  // 不知数量
let colors = new Array(20); //  已知数量
let colors = new Array("red","blue");  // 直接传入元素
let colors = ["red","blue"]; // 字面量法

除此之外,还有两个方法,可以将看起来像数组,但本身不是数组的数据转换成数组,就是from()、of()。

什么叫"像而不是",比如类数组,当我们通过DOM API document.getElementsByTagName()等获取到一组NodeList,就是类数组。

类数组只具备一部分数组的能力,有length属性,可通过索引访问元素,但不能正常使用数组的方法,如果需要,就可以用Array.from()方法将其转换为数组再使用。

of()方法则用于将一组参数转换为数组,如 Array.of(1,2,3,4),结果是 [1,2,3,4]。

数组方法

数组如此常用,肯定存在很多情况需要处理,于是JavaScript赋予了它一众强大的方法,这些方法为实际项目中各种需求提供了便利,此处介绍一部分。

数组项方法

less 复制代码
let colors = ["red","blue"]; // 原本是这样
colors.push("yellow")
["red","blue","yellow"];  // 操作后

除此之外,还有shift(取第一项)、unshift(头部添加)、pop(取最后一项)

迭代方法

包括forEach、map、filter等,它们对数组的每一项运行其中的函数体,并根据各自的能力返回相应结果。

forEach遍历数组项,没有返回值,类似for循环。

map返回代码逻辑中指定的返回值,组成新的数组。

filter返回代码中条件判断为true的数组项,组成新的数组。

dart 复制代码
let numbers = [2,1,3]
let newNumbers = numbers.map(num=>{
	return num + 1
})
// [3,2,4]
let newNumbers = numbers.filter(num=>{
	return num > 1
})
// [2,3]

除以上方法外,数组还有很多其他实用方法,如"reverse(反转)、sort(排序)、reduce(归并)、includes(包含)、flat(展开)"等,相当丰富,可满足各种需求,篇幅原因不一一介绍,各位根据需要拓展学习。

笔者在最初学习时,曾苦于方法过多难以记忆,现在告诉你,不用记,没有比实践带来的印象更深,用到的时候多查,用多了自然记住。

定型数组

JavaScript中本没有定型数组(Typed Array),它的行为也与普通数组有所差异,它是什么,又为何存在?

定型数组指的是一种特殊的包含数值类型的数组。设计的目的是提升向原生库传输数据的效率,如:WebGL。

就是说,JavaScript会与WebGL产生交互,但二者的数据格式不同,需要额外处理,这就带来更多消耗。

当你看到Float32Array,Int32Array、ArrayBuffer、DateView等略感陌生的数据时,就代表定型数组出现了。

ArrayBuffer是所有定型数组的基本单位,当使用WebAssembly时,可能见到ShareArrayBuffer,它是ArrayBuffer的一种变体。

定型数组的应用尚不广泛,初步了解这就够了。

Map

Map是ES6中加入的新的集合类型,它带来了真正的键-值存储机制。

什么叫"真正",还有假的?

很长一段时间内,这个角色都由Object在扮演。

编码的灵活性决定了一些代码的功能可用另一种替代,这就是典型的例子,Map的多数特性Object都可以实现,但是专一职责原则又告诉我们它该有更确切的实现。

基本API

dart 复制代码
const m = new Map();
m.set("name","说书匠").set("age",18);
m.has("name"); // true
m.get("name"); // "说书匠"
m.size   // 2
m.delete("age")  // age被删
m.clear();  // map清空

由上可见,Map中添加、判断和查找键值是很直观的,你或许发现了第二行的特殊之处,set后面又跟了个set,因为set本身会返回映射的实例,就又可以接着用了。

与Object只能用数值、字符串或符号作为键不同,Map可以使用任意JavaScript数据类型作为键,值也没有限制。

除此之外,在迭代方面也有差异,Map实例会维护键-值对的插入顺序,可以根据插入顺序执行迭代操作。可用的方法有keys()、values()、entries()等。

它们对于内存占用的情况也不同,固定内存情况下,Map可以比Object多存储50%左右的键-值对。

在插入、查找、删除等操作的性能上,Map也比Object更优,所以,需要用到键-值对的时候,我们可以调整一下编码习惯,优先选择Map。

Set

Set是另一种新增的集合型数据结构,像加强版的Map,因为它们多数API是相似的,正因如此,学习起来较为轻松。

基本API

scss 复制代码
const m = new Set([1,2,3])
m.size  // 3
m.add(4).add(5)
m.has(3)  // true 
m.delete(1)
m.clear()

操作同样直观易懂,不赘述。

既然是集合,也能迭代,Set的迭代也是支持顺序的,同样支持keys()、values()、entries()等。

其实,从形式上看,Set更像Array,没有键,只有值,那么这两者间又该如何选用呢?

每种数据结构的选择都应有原因,不妨做个对比。

适合Set场景:

1、需要存储不重复的唯一值

2、频繁检查元素是否存在

3、需要数学集合运算

4、需要频繁增删

适合Array场景:

1、需要有序

2、索引访问。

必要时,二者还可相互转换:

sql 复制代码
// Array转Set
const m = new Set([1,2,3])
// Set转Array
[...m]

最后这个"..."操作是什么?

三个点也是一种操作符,叫"扩展"操作符,它可用于普通的对象、数组和Set这种集合类数据中,相当于把后面变量包含的值放到当前"容器"中。

同时,集合类型的数据都支持 for-of 循环,对于迭代访问每个值就方便多了。

弱引用

这是与JavaScript中垃圾回收相关的一个机制,我们定义的变量,引擎会自动管理它们占的内存,通常来说,当某个对象不再使用,垃圾回收器会释放它占的内存。

如果我们想保持对对象的引用,同时不阻止它被回收的行为,这种引用就称为"弱引用"。

弱引用的创建方式有三种:WeakRef、WeakMap、WeakSet 。分别对应Object、Map和Set

除了不阻止垃圾回收,它们在特性和操作上跟前面介绍的也有区别。

WeakMap和WeakSet中的键只能是Object或者继承自Object的类型,同时,它们不可迭代,没有clear()方法。

小结

集合类型之常见,每个项目,甚至每个文件,都会有它们的身影,其中以数组最为常用,所以,掌握它们是必须的。

但正如前文所述,集合在某种程度上是对数据的存储和管理,像载体,最终,我们还是要拿到具体的每个值去做分析和处理,这时候,增删改,迭代方法,就很重要了,恰恰JavaScript提供了非常丰富又实用的方法,希望大家多加练习,熟练掌握,在开发时就能游刃有余。

更多好文第一时间接收,可关注公众号:"前端说书匠"

相关推荐
恋猫de小郭31 分钟前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅7 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60618 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了8 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅8 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅9 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment9 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅9 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊9 小时前
jwt介绍
前端