字典是一种以 键 - 值 对形式存储结构的数据结构, 就像电话号码薄里的名字和电话号码一样. 要找一个电话时, 先找名字, 名字找到了, 紧挨着它的电话号码也就找到了. 这里的 键 是指你用来查找的东西, 值 是查找得到的结果.JS
的Object
类就是以字典形式设计的. 本章将使用Object
类本身的特性, 实现一个Dictionary
类, 让这种字典类型的对象使用起来更加简单. 你也可以只使用数组和对象来实现本章展示的方法, 但是定义一个Dictionary
类更方便, 也更有意思. 比如, 使用()
引用键就比使用[]
简单. 当然, 还有其他一些便利, 比如可以定义对整体进行操作的方法, 举个栗子, 显示字典中所有的元素, 这样就不必在主程序中循环去遍历字典了.
Dictionary
类
Dictionary
类是基础是Array
类, 而不是Object
类. 本章稍后将提到, 我们想对字典中的键排序, 而JS
中是不能对对象的属性进行排序的. 但是也不要忘记, JS
中一切皆对象, 数组也是对象.
window.log = console.log.bind(console)class Dictionary { constructor() { this._datastore = []; } add(key, value) { this._datastore[key] = value; } find(key) { return this._datastore[key]; } remove(key) { delete this._datastore[key]; } showAll() { Object.keys(this._datastore).forEach(key => { log(`${key} ===>>> ${this._datastore[key]}`) }) }};const pbook = new Dictionary();pbook.add('作家1', '书1');pbook.add('作家2', '书2');pbook.add('作家3', '书3');pbook.add('作家4', '书4');pbook.showAll();log('')pbook.remove('作家3');pbook.showAll();
add()
方法接受两个参数: 键和值. 键是值在字典中索引.
find()
方法以键为参数, 返回和其相关联的值.remove()
方法用到了JS
中的一个内置函数: delete
.该函数是Object
类的一部分, 使用对键的引用作为参数. 该函数同时删掉键和与其关联的值.showAll()
方法显示字典中所有的键值对. Dictionary
类的辅助方法
我们还可以定义一些在特定情况下用的辅助方法.
...count() { let n = 0; Object.keys(this._datastore).forEach(i => { n++ }); return n;}clear() { Object.keys(this._datastore).forEach(key => { delete this._datastore[key] });}...
比如, 要是能知道字典中的元素个数就好了, 那么就可以定义一个count()
方法.
_datastore
是数组类型的话为什么不直接用length
属性呢? 这是因为当键的类型为字符串时, length
属性就不管用了. eg: const nums = [];nums[0] = 1;nums[1] = 2;log(nums.length); // 2const book = [];book['a'] = 1;book['b'] = 2;log(book.length); // 0
以及清空字典clear()
. 这里使用this._datastore = []
也是可以的;
为Dictionary
类添加排序功能
字典的主要用途是通过键取值, 我们无需太关心数据在字典中的实际存储顺序. 然而, 很多人都希望看到一个有序的字典. 下面来看看如何让前面的字典按顺序显示.
数组是可以排序的, eg:
const a = [];a[0] = 'm';a[1] = 'd';log(a); // m da.sort();log(a); // d m
但是上面的这种做法是对字符串作为键的字典无效的, 程序会没有任何输出. 这和我们前面定义count()
方法时情况一致;
不过这也不是大问题. 用户关心的是显示字典的内容时, 结果是有序的. 可使用Object.keys()
函数解决这个问题, 重新定义showAll()
方法:
showAll() { Object.keys(this._datastore).sort().forEach(key => { log(`${key} ===>>> ${this._datastore[key]}`) })}
和前面的区别是: 拿到_datastore
的键后, 调用sort()
方法对键重新排序.