在前端开发的多彩世界里,数据结构是我们构建应用的基石。四种看似普通的结构——Map、Set、对象和数组——实则蕴藏着强大的力量。它们不仅支撑着我们日常的编码任务,更在性能优化和代码可读性上扮演着关键角色
为什么引入 Map 和 Set
-
填补现有数据结构的空缺:在 ES6 之前,JavaScript 缺乏内置的
键值对
和集合数据结构
,Map 和 Set 的引入填补了这一空缺。 -
提高性能:对于特定的操作,Map 和 Set 提供了比传统对象和数组
更优的性能
。 -
增强语言特性:Map 和 Set 的引入增强了 JavaScript 作为一门编程语言的特性,使其更加现代化和功能丰富,
更清晰的 API
。 -
更好的数据结构支持:随着 Web 开发需求的增加,开发者需要更高效的数据结构来处理复杂的数据,
Map 允许任何类型的键,而 Set 自动去重
, Map 和 Set 提供了这样的支持,
API 介绍
Map
Map
是一种集合类型,它存储键值对的集合,其中键和值可以是任何类型。Map
对象保存插入顺序的元素。
Map 的基本 API
new Map()
:创建一个新的 Map 对象。map.set(key, value)
:将一个键值对添加到 Map 中。map.get(key)
:返回 Map 中与指定键关联的值。map.has(key)
:检查 Map 中是否存在指定的键。map.delete(key)
:从 Map 中删除指定的键。map.clear()
:清除 Map 中的所有键值对。map.size
:返回 Map 中元素的数量。map.keys()
:返回一个迭代器,包含 Map 中的所有键。map.values()
:返回一个迭代器,包含 Map 中的所有值。map.entries()
:返回一个迭代器,包含 Map 中的所有键值对。
Map 示例代码
创建 map 对象
let map = new Map();
设置值
map.set("key1", "value1");
map.set("key2", "value2");
获取值
console.log(map.get("key1")); // 输出:value1
遍历全部
for (let [key, value] of map) {
console.log(`${key}: ${value}`);
}
查询值
console.log(map.has("key2")); // 输出:true
console.log(map.size); // 输出:1
删除值
map.delete("key1");
map.clear();
Set
Set
是一种集合类型,它只存储唯一的值。
Set 的基本 API
new Set()
:创建一个新的 Set 对象。set.add(value)
:添加一个元素到 Set 中。set.delete(value)
:从 Set 中删除指定的元素。set.has(value)
:检查 Set 中是否存在指定的元素。set.clear()
:清除 Set 中的所有元素。set.size
:返回 Set 中元素的数量。
Set 示例代码
创建 set 对象
let set = new Set();
设置值
set.add(1);
set.add(2);
获取值
for (let value of set) {
console.log(value);
}
查询值
console.log(set.has(1)); // 输出:true
console.log(set.size); // 输出:2
删除值
set.delete(1);
set.clear();
对象
在 JavaScript 中,对象是键值对的集合,键是字符串(或符号),值可以是任意类型。
对象的基本 API
obj[key]
:访问或设置对象的属性。delete obj[key]
:删除对象的属性。Object.keys(obj)
:返回一个包含对象所有自身属性的数组。Object.values(obj)
:返回一个包含对象所有自身属性值的数组。Object.entries(obj)
:返回一个给定对象自身可枚举属性的键值对数组。
对象示例代码
// 创建方式1
let obj = { a: 1, b: 2 };
// 创建方式2
let obj_null = Object.create(null);
// 获取值
console.log(obj.a); // 输出:1
// 赋值
obj.c = 3;
// 获取keys,values
console.log(Object.keys(obj)); // 输出:['a', 'b', 'c']
console.log(Object.values(obj)); // 输出:[1, 2, 3]
// 遍历
for (let key in obj) {
console.log(`${key}: ${obj[key]}`);
}
数组
数组是有序的数据项集合。
数组的基本 API
array[index]
:访问或设置数组的元素。array.length
:获取或设置数组的长度。array.push(element)
:向数组末尾添加一个或多个元素。array.pop()
:移除数组的最后一个元素并返回该元素。array.shift()
:移除数组的第一个元素并返回该元素。array.unshift(element)
:在数组的开头添加一个或多个元素。array.slice(start, end)
:返回一个新的数组,包含从 start 到 end(不包括 end)的原数组元素。array.includes(element)
:判断数组是否包含指定的元素。
数组示例代码
let array = [1, 2, 3];
console.log(array[0]); // 输出:1
array.push(4);
console.log(array.length); // 输出:4
// pop 从尾部移除、 shift 从数组前面移除
array.pop(); // 移除4
// 检查
console.log(array.includes(2)); // 输出:true
// 遍历
for (let i = 0; i < array.length; i++) {
console.log(array[i]);
}
API 转换
Map 转对象
let mapToObject = Object.fromEntries(map);
对象转 Map
let objectToMap = new Map(Object.entries(obj));
Set 转数组
let setToArray = [...set];
数组转 Set
let arrayToSet = new Set(array);
for...of 与 for...in
for..of
for...of 循环是一种用于
遍历可迭代对象(iterable)
的 JavaScript 语法。它允许你遍历数组、字符串、Map、Set以及任何实现了[Symbol.iterator]属性的对象。
可迭代对象
可迭代对象是具有默认迭代器的对象。迭代器是一个具有 next()方法的对象,该方法返回包含两个属性的对象:value 和 done。value 是迭代器当前返回的值,done 是一个布尔值,表示迭代器是否已经遍历完所有元素。
for...of 循环的原理
- 获取迭代器:for...of 循环首先调用可迭代对象的Symbol.iterator方法,获取一个迭代器。
- 执行迭代:然后,循环使用迭代器的
next()
方法来获取下一个值。 - 循环继续条件:for...of 循环会检查
next()
方法返回的done
属性。如果 done 是 false,则循环继续,并将 value 赋值给循环变量。 - 循环结束条件:当 done 属性为 true 时,循环结束。
- 循环体执行:在每次迭代中,循环体中的代码会被执行,使用当前的 value。
让对象拥有 for...of 能力
let obj = {
a: "001",
b: "002",
c: "003",
[Symbol.iterator]() {
let index = 0;
const items = Object.keys(obj);
return {
next: () => {
if (index < items.length) {
return { value: items[index++], done: false };
} else {
return { done: true };
}
},
};
},
};
for (let item of obj) {
console.log(item); // 依次输出 a,b,c
}
for...in
for...in 循环用于遍历对象的属性名(
包括可枚举的自有属性和继承的属性
)。
提一下,
Object.keys()
获取到的 keys 不包含原型链中的 key,这是Object.keys 遍历
和for...in
的区别
特点:
- 遍历对象的键(属性名)。
- 不保证遍历的顺序。
- 通常与 hasOwnProperty() 方法结合使用,以避免遍历原型链上的属性。
示例
let obj = { a: 1, b: 2, c: 3 };
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key + ": " + obj[key]); // 输出:a: 1, b: 2, c: 3
}
}
结语
经过对 Map、Set、对象和数组的深入剖析,我们不仅理解了它们各自的特性和用途,还学会了如何根据实际需求选择合适的数据结构。从填补 JavaScript 早期的空缺到成为现代 Web 开发中不可或缺的工具,Map 和 Set 的出现极大地丰富了我们处理数据的能力。同时,我们也认识到了对象和数组在 JavaScript 中的经典地位以及它们在特定场景下的不可替代性。
通过本文的 API 介绍和示例代码,掌握了如何有效地使用这些数据结构,并了解了它们之间的转换方法。无论是在性能优化、代码清晰度还是功能需求上,我们都有了一个更加明确的选择方向。能够更加自信地在前端开发中运用这些数据结构,打造出更加高效、优雅的代码。