JavaScript 数据结构之字典方法
本文深入解析 JavaScript 中的字典数据结构,对比其与集合的区别,阐述键值对存储原理。通过手动实现 Dictionary 类,详细讲解 set、get、remove 等核心方法的逻辑,并展示 ES6 Map 的原生用法,帮助开发者理解底层机制与最佳实践。
前言:
经过上一篇JavaScript 数据结构之集合创建(2)的学习,数据结构的集合部分已经完结了。那么下面我们又要认识一个新的数据结构,它的名字相信你绝不陌生,它就是字典。
这里的字典并非指用于查阅汉字的工具书。在数据结构领域,字典同样用于存储唯一且不可重复的值,这一点与集合有相似之处。然而,两者的存储机制存在显著差异。
集合侧重于元素本身,以元素的值作为唯一标识。而字典采用 键值对 的形式进行存储,这种格式我们非常熟悉。它以 key 作为标识符,value 作为对应的值,这与我们常见的 JSON 格式如出一辙。
下面我们从基础概念开始,逐步学习字典的实现与用法。
一、什么是字典
前文提到,集合通过元素的值来确定其唯一性。而在字典中,存储方式表现为键值对,即 key->value 的形式。字典仅要求 key 必须唯一,对 value 的值类型没有限制。
在此结构中,key 起到唯一标识的作用,用于查询对应的 value。也就是说,可以通过唯一的 key 映射到特定的 value。因此,字典也常被称为映射、符号表或关联数组。
在计算机领域,字典常用于标识对象的引用地址。例如在 JavaScript 中的 引用类型 数据中,变量名指向数据的引用地址,形成一种映射关系。变量名不能重复,但不同的变量名可以指向同一块引用内存。
与 Set 类似,JavaScript ES6 标准中也提供了一个 Map 类,即我们通常所说的字典。
二、创建字典类
接下来,我们将参考 ES6 Map 类的实现方式,手动构建一个 Dictionary 类。
class Dictionary {
constructor() {
this.table = {}
}
}与其他数据结构的实现类似,我们使用一个对象 table 来存储字典中的所有元素。其保存形式为:table[key] = {key, value}。
在字典中,通常使用字符串作为键名(key),而数据值可以是任意类型。由于 JavaScript 并非强类型语言,无法保证传入的键名一定是字符串,因此我们需要对键名进行字符串转换处理。
编写一个默认的字符串转换函数:
function keyToString(item) {
if(typeof item === null) {
return 'NULL'
}
if(typeof item === undefined) {
return 'UNDEFINED'
}
if(item instanceof String) {
return `${item}`
}
return item.toString()
}此外,我们还需要将键值对的数据格式封装为一个独立的类。因为 key 是不固定的,而在后续方法中会频繁使用 key,此时无法预知具体的键名。因此,需要封装一个 ValuePair 类,定义如下:
class ValuePair {
constructor(key, value) {
this.key = key;
this.value = value;
}
}接下来在类中声明以下必要的方法:
set:向字典中添加新元素remove:以键名为参数,移除字典中对应的键值hasKey:检测某个键名是否存在于字典中,存在则返回 trueget:用键名查找对应的键值并返回clear:清空字典size:返回字典所包含键的数量isEmpty:在 size 等于零时返回 truekeys:返回字典中所有键名组成的数组values:返回字典中所有键值组成的数组keyValues:返回所有键值对forEach:迭代所有的键值对
1.hasKey 方法
该方法用于检测一个键是否存在于字典中。由于此方法会在添加和删除元素时被调用,因此优先实现:
hasKey(key) {
return this.table[keyToString(key)] != null
}首先对传入的键进行字符串转换,然后判断键值是否为 null 或 undefined。
2.set 方法
set 方法用于在字典中添加键值对:
set(key, value) {
if(key != null && value != null) {
let table_key = keyToString(key)
this.table[table_key] = new ValuePair(key, value)
return true
}
return false
}3.remove 方法
remove 方法用于删除字典中的一个键值对:
remove(key) {
if(this.hasKey(key)) {
delete this.table[keyToString(key)]
return true
}
return false
}4.get 方法
get 方法用于获取键名对应的键值:
get(key) {
if(this.hasKey(key)) {
let table_key = keyToString(key)
return this.table[table_key].value
}
return undefined
}5.keys, values, keyValues 方法
这三个是较为简单的辅助函数,一并介绍:
keyValues() {
return Object.values(this.table)
}
keys() {
return this.keyValues().map(valuePair=> valuePair.key)
}
values() {
return this.keyValues().map(valuePair=> valuePair.value)
}首先 keyValues 方法以数组形式返回字典的所有键值,结果为一个 ValuePair 实例的数组。在此基础上,分别获取对应的 key 数组和 value 数组。
6.forEach 方法
forEach 方法与数组的 forEach 功能一致,用于迭代所有元素。我们来看一下如何迭代字典的所有值:
forEach(callFn) {
let valuePairs = this.keyValues()
for(let i = 0; i < valuePairs.length; i++) {
let result = callFn(valuePairs[i].key, valuePairs[i].value)
if(result === false) break;
}
}首先传入一个回调函数作为参数,然后遍历字典的长度,并在循环中调用该回调函数。这里的设计是,如果在回调函数内返回 false,则会中断循环。
7.clear, size, isEmpty 方法
这三个方法相对基础:
size() {
return Object.keys(this.table).length;
}
isEmpty() {
return this.size() === 0
}
clear() {
this.table = {}
}三、使用字典
前文我们编写了多个方法来实现字典类,现在来实际使用一下:
var dict = new Dictionary();
dict.set("name", "赛罗");
dict.set("color", "红蓝");
dict.set("skill", "头标");添加了三个键值对,我们查看基本方法的返回结果:
console.log(dict.keys()); // ['name', 'color', 'skill']
console.log(dict.values()); // ['赛罗', '红蓝', '头标']
console.log(dict.size()); // 3
console.log(dict.hasKey("color")); // true
console.log(dict.get("color")); // 红蓝
console.log(dict.hasKey("like")); // false
console.log(dict.get("like")); // undefined看结果都没问题,再来一波遍历:
dict.forEach((key, value) => {
console.log(key, value);
if (key === "color") return false;
});
// 打印结果:
// name 赛罗
// color 红蓝可见循环遍历没有问题。当函数执行返回 false 时,遍历将终止,因此第三个键值对未被打印,结果符合预期。
最后再看一下删除操作:
// 删除键值对
console.log(dict.remove("color")); // true
console.log(dict.remove("like")); // false
console.log(dict.remove("skill")); // true
console.log(dict.keyValues()); // [ValuePair]
console.log(dict.hasKey("color")); false
console.log(dict.size()); 1
// 清空字典
dict.clear();
console.log(dict.keyValues()); // []
console.log(dict.isEmpty()); // true结果完美,没有任何问题!
四、总结
本篇从头至尾介绍了字典的相关知识,你学会了吗?尽管 ES6 提供了原生支持,但对于学习者而言,手动实现一次更有助于深入理解其原理。
到此这篇关于 JavaScript 数据结构之字典方法的文章就介绍到这了,更多相关 JavaScript 字典内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!
JS读取本地文件时报错或无响应的常见原因
2026-11-05 16:32:31
let、const与var的区别:JavaScript变量声明最佳实践
2026-11-05 14:16:38
JS中直接定义静态二维数组的字面量写法
2026-11-05 14:16:08
JS 怎么查找字符串中所有匹配项的位置
2026-11-05 14:15:53
JavaScript新手常犯的编码错误与最佳实践指南
2026-11-04 22:12:38
