前端面试八之map
Map
是 JavaScript 中的一个内置对象,它是一种键值对的集合,类似于对象(Object
),但有一些重要的区别和优势。Map
提供了更强大的功能,特别是在处理键值对时更加灵活和高效。
1. Map 的基本特性
(1)键值对
-
Map
是一个简单的键值对集合,其中每个键都映射到一个值。 -
键可以是任何数据类型(包括对象、函数等),而不仅仅是字符串或符号(
Symbol
)。 -
值也可以是任何数据类型。
(2)保持插入顺序
-
Map
会按照插入的顺序保存键值对。这意味着当你遍历Map
时,键值对会按照插入的顺序返回。
(3)动态大小
-
Map
的大小是动态的,可以根据需要添加或删除键值对。
2. 创建 Map
可以通过以下方式创建一个 Map
:
const myMap = new Map();
也可以通过一个数组的数组(键值对数组)初始化 Map
:
const myMap = new Map([['key1', 'value1'],['key2', 'value2'],[3, 'value3'],[{ id: 1 }, 'value4'],
]);
3. Map 的常用方法
(1)set(key, value)
:添加或更新键值对
(2)保持插入顺序
(3)动态大小
2. 创建 Map
可以通过以下方式创建一个 Map
:
JavaScript
复制
const myMap = new Map();
也可以通过一个数组的数组(键值对数组)初始化 Map
:
JavaScript
复制
const myMap = new Map([['key1', 'value1'],['key2', 'value2'],[3, 'value3'],[{ id: 1 }, 'value4'],
]);
3. Map 的常用方法
(1)set(key, value)
:添加或更新键值对
JavaScript
复制
myMap.set('key1', 'newValue1');
myMap.set('key3', 'value3');
(2)get(key)
:获取键对应的值
JavaScript
复制
console.log(myMap.get('key1')); // 输出: newValue1
console.log(myMap.get('key3')); // 输出: value3
console.log(myMap.get('key4')); // 输出: undefined
(3)has(key)
:检查键是否存在
JavaScript
复制
console.log(myMap.has('key1')); // 输出: true
console.log(myMap.has('key4')); // 输出: false
(4)delete(key)
:删除键值对
JavaScript
复制
console.log(myMap.delete('key1')); // 输出: true
console.log(myMap.delete('key4')); // 输出: false
(5)clear()
:清空所有键值对
JavaScript
复制
myMap.clear();
(6)size
:获取键值对的数量
JavaScript
复制
console.log(myMap.size); // 输出: 0(如果已经调用了 clear)
4. 遍历 Map
Map
提供了多种遍历方式,包括 for...of
循环、forEach
方法等。
(1)for...of
循环
(2)性能
(3)保持顺序
(4)内置方法
-
如果键已存在,则更新其值。
-
如果键不存在,则添加新的键值对。
myMap.set('key1', 'newValue1'); myMap.set('key3', 'value3');
(2)
get(key)
:获取键对应的值 -
如果键存在,返回对应的值。
-
如果键不存在,返回
undefined
。console.log(myMap.get('key1')); // 输出: newValue1 console.log(myMap.get('key3')); // 输出: value3 console.log(myMap.get('key4')); // 输出: undefined
(3)
has(key)
:检查键是否存在 -
如果键存在,返回
true
。 -
如果键不存在,返回
false
。console.log(myMap.has('key1')); // 输出: true console.log(myMap.has('key4')); // 输出: false
(4)
delete(key)
:删除键值对 -
如果键存在,删除键值对并返回
true
。 -
如果键不存在,返回
false
。console.log(myMap.delete('key1')); // 输出: true console.log(myMap.delete('key4')); // 输出: false
(5)
clear()
:清空所有键值对 -
删除
Map
中的所有键值对。myMap.clear();
(6)
size
:获取键值对的数量 -
返回
Map
中的键值对数量。console.log(myMap.size); // 输出: 0(如果已经调用了 clear)
Map
是 JavaScript 中的一个内置对象,它是一种键值对的集合,类似于对象(Object
),但有一些重要的区别和优势。Map
提供了更强大的功能,特别是在处理键值对时更加灵活和高效。1. Map 的基本特性
(1)键值对
-
Map
是一个简单的键值对集合,其中每个键都映射到一个值。 -
键可以是任何数据类型(包括对象、函数等),而不仅仅是字符串或符号(
Symbol
)。 -
值也可以是任何数据类型。
-
Map
会按照插入的顺序保存键值对。这意味着当你遍历Map
时,键值对会按照插入的顺序返回。 -
Map
的大小是动态的,可以根据需要添加或删除键值对。 -
如果键已存在,则更新其值。
-
如果键不存在,则添加新的键值对。
-
如果键存在,返回对应的值。
-
如果键不存在,返回
undefined
。 -
如果键存在,返回
true
。 -
如果键不存在,返回
false
。 -
如果键存在,删除键值对并返回
true
。 -
如果键不存在,返回
false
。 -
删除
Map
中的所有键值对。 -
返回
Map
中的键值对数量。 -
遍历
Map
的键值对。const myMap = new Map([['key1', 'value1'],['key2', 'value2'], ]);for (const [key, value] of myMap) {console.log(key, value); } // 输出: // key1 value1 // key2 value2
(2)
forEach
方法 -
遍历
Map
的键值对。myMap.forEach((value, key) => {console.log(key, value); }); // 输出: // key1 value1 // key2 value2
(3)
keys()
、values()
和entries()
方法 -
keys()
:返回一个包含所有键的迭代器。 -
values()
:返回一个包含所有值的迭代器。 -
entries()
:返回一个包含所有键值对的迭代器。for (const key of myMap.keys()) {console.log(key); } // 输出: // key1 // key2for (const value of myMap.values()) {console.log(value); } // 输出: // value1 // value2for (const [key, value] of myMap.entries()) {console.log(key, value); } // 输出: // key1 value1 // key2 value2
5. Map 与 Object 的区别
(1)键的类型
-
Object
:键只能是字符串或符号(Symbol
)。 -
Map
:键可以是任何数据类型(包括对象、函数等)。 -
Object
:在处理大量数据时,性能可能会下降,尤其是在频繁添加和删除键值对时。 -
Map
:在处理大量数据时性能更好,尤其是在频繁添加和删除键值对时。 -
Object
:不保证键的顺序。 -
Map
:按照插入顺序保存键值对,遍历时会按照插入顺序返回。 -
Object
:没有内置的size
属性或clear
方法。 -
Map
:提供了size
属性和clear
方法。 -
Object
:没有内置的size
属性或clear
方法。 -
Map
:提供了size
属性和clear
方法。
6. 使用场景
Map
适用于以下场景:
-
需要存储键值对,且键的类型不局限于字符串或符号。
-
需要频繁添加和删除键值对。
-
需要保持键值对的插入顺序。
-
需要高效地遍历键值对。
7. 示例:使用 Map 处理三级下拉框数据
以下是一个完整的示例,展示如何在 Vue 2 中使用 Map
处理三级下拉框的数据。
数据结构
const data = [{id: 1,name: '省份1',cities: [{id: 11,name: '城市1-1',areas: [{ id: 111, name: '区域1-1-1' },{ id: 112, name: '区域1-1-2' },],},{id: 12,name: '城市1-2',areas: [{ id: 121, name: '区域1-2-1' },{ id: 122, name: '区域1-2-2' },],},],},{id: 2,name: '省份2',cities: [{id: 21,name: '城市2-1',areas: [{ id: 211, name: '区域2-1-1' },{ id: 212, name: '区域2-1-2' },],},{id: 22,name: '城市2-2',areas: [{ id: 221, name: '区域2-2-1' },{ id: 222, name: '区域2-2-2' },],},],},
];
Vue 组件
<template><div><h1>三级下拉框示例</h1><el-selectv-model="selectedProvince"placeholder="请选择省份"@change="onProvinceChange"><el-optionv-for="province in data":key="province.id":label="province.name":value="province.id"></el-option></el-select><el-selectv-model="selectedCity"placeholder="请选择城市"@change="onCityChange":disabled="!selectedProvince"><el-optionv-for="city in provinceMap.get(selectedProvince)?.cities":key="city.id":label="city.name":value="city.id"></el-option></el-select><el-selectv-model="selectedArea"placeholder="请选择区域"@change="onAreaChange":disabled="!selectedCity"><el-optionv-for="area in cityMap.get(selectedCity)?.areas":key="area.id":label="area.name":value="area.id"></el-option></el-select></div>
</template><script>
export default {data() {return {data, // 原始数据provinceMap: new Map(), // 省份 MapcityMap: new Map(), // 城市 MapselectedProvince: null, // 选中的省份selectedCity: null, // 选中的城市selectedArea: null, // 选中的区域};},created() {this.initializeMaps();},methods: {initializeMaps() {// 初始化省份 Mapthis.data.forEach(province => {this.provinceMap.set(province.id, province);province.cities.forEach(city => {this.cityMap.set(city.id, city);});});},onProvinceChange(provinceId) {this.selectedProvince = provinceId;this.selectedCity = null;this.selectedArea = null;},onCityChange(cityId) {this.selectedCity = cityId;this.selectedArea = null;},onAreaChange(areaId) {this.selectedArea = areaId;},},
};
</script>
代码解释
(1)initializeMaps
方法
-
在
created
钩子中调用initializeMaps
方法。 -
将省份和城市的数据分别存储到
provinceMap
和cityMap
中。 -
这样可以快速通过省份 ID 获取省份数据,通过城市 ID 获取城市数据。
(2)onProvinceChange
方法
-
当省份发生变化时,更新
selectedProvince
。 -
清空城市和区域的选择,因为省份变化后,城市和区域的选择需要重新选择。
(3)onCityChange
方法
-
当城市发生变化时,更新
selectedCity
。 -
清空区域的选择,因为城市变化后,区域的选择需要重新选择。
(4)onAreaChange
方法
-
当区域发生变化时,更新
selectedArea
。
(5)模板中的动态绑定
-
使用
v-model
绑定选中的省份、城市和区域的 ID。 -
使用
v-for
动态生成下拉框的选项。 -
使用
:disabled
属性控制下拉框的启用状态,确保只有在选中上一级时才能选择下一级。
效果
运行项目后,你将看到一个包含三级下拉框的页面。选择省份后,城市下拉框会动态更新;选择城市后,区域下拉框会动态更新。
总结
通过使用 Map
处理三级下拉框的数据,可以实现高效的级联选择功能。这种方式不仅代码清晰,而且性能优越,特别适合处理复杂的数据结构。