JavaScript 数据结构之字典方法

作者:青柠时间:2026-10-25 09:28:26浏览:308

本文深入解析 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:检测某个键名是否存在于字典中,存在则返回 true
  • get:用键名查找对应的键值并返回
  • clear:清空字典
  • size:返回字典所包含键的数量
  • isEmpty:在 size 等于零时返回 true
  • keys:返回字典中所有键名组成的数组
  • 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 字典内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

作者最新文章