字典中,键名最理想的情况是字符串,值可以是任何类型。但是JavaScript不是强类型的语言,所有需要将key转换为字符串。
function defaultToString(item) {
if (item === null) {
return 'NULL';
} else if (item === undefined) {
return 'UNDEFINED';
} else if (typeof item === 'string' || item instanceof String) {
return `${
item}`;
}
return item.toString();
}
Dictionary类的骨架:
class Dictionary {
constructor(toStrFn = defaultToString) {
// 将key转换为字符串
this.toStrFn = toStrFn;
// 将[键,值]对保存为 table[key] = {key, value}
this.table = {
};
}
}
一些常用方法:
hasKey(key)方法会被set和remove等方法调用,需要先实现
hasKey(key) {
// 如果已经存在一个给定键名的键值对,返回true,否则返回false
return this.table[this.toStrFn(key)] != null;
}
set方法:接收key和value作为参数。可用于添加新的值,或更新已有的值
set(key, value) {
// 如果key和value不为null或undefined
if (key != null && value != null) {
// 获取key的字符串
const tableKey = this.toStrFn(key);
// 创建一个新的键值对并将其赋值给table对象上的key属性
// 此处还需要实例化ValuePair类
this.table[tableKey] = new ValuePair(key, value);
return true;
}
return false;
}
ValuePair类定义如下:
class ValuePair {
constructor(key, value) {
this.key = key;
this.value = value;
}
toString() {
return `$[#${
this.key}: ${
this.value}]`
}
}
为了保存信息的需要,要保存原始的key。因此,我们不是只将value保存在字典中,而是要保存两个值:原始的key和value
实现时要先搜索key,而不是value
remove(key) {
if (this.hasKey(key)) {
delete this.table[this.toStrFn(key)];
return true;
}
return false;
}
方式一:(消耗比第二种方式少)
get(key) {
// 检索存储在给定key属性中的对象
const valuePair = this.table[this.toStrFn(key)];
return valuePair == null ? undefined : valuePair.value;
}
方式二:
会获取两次key的字符串以及访问两次table对象:第一次是在hasKey方法中,第二次是在if语句内
get(key) {
if (this.hasKey(key)) {
return this.table[this.toStrFn(key)];
}
return undefined;
}
返回字典中所有键值对:
// ES2017引入Object的values方法
keyValues() {
return Object.values(this.table);
}
所有浏览器都支持的方式:
keyValues() {
const valuePairs = [];
for (const k in this.table) {
if (this.hasKey(k)) {
valuePairs.push(this.table[k]);
}
}
return valuePairs;
}
返回字典中所有(原始)键名:
keys() {
// 调用所创建的keyValues方法来返回一个包含valuePair实例的数组,然后迭代每个valuePair并只返回它的key。
return this.keyValues().map(valuePair => valuePair.key);
}
返回字典中包含的所有值构成的数组:
values() {
return this.keyValues().map(valuePair => valuePair.value);
}
forEach(callbackFn) {
// 获取字典中所有valuePair构成的数组
const valuePairs = this.keyValues();
for (let i = 0; i < valuePairs.length; i++) {
// 执行以参数形式传入forEach方法的callbackFn函数
const result = callbackFn(valuePairs[i].key, valuePairs[i].value);
// 如果回调函数返回了false,中断forEach方法的执行,打断正在迭代valuePairs的for循环
if (result === false) {
break;
}
}
}
size() {
return Object.keys(this.table).length;
// 或者
// return this.keyValues().length;
}
isEmpty() {
return this.size() === 0;
}
clear() {
this.table = {
};
}
toString() {
if (this.isEmpty()) {
return '';
}
const valuePairs = this.keyValues();
let objString = `${
valuePairs[0].toString()}`;
for (let i = 1; i < valuePairs.length; i++) {
objString = `${
objString}, ${
valuePairs[i].toString()}`;
}
return objString;
}
const dictionary = new Dictionary();
dictionary.set('aaa', '[email protected]');
dictionary.set('bbb', '[email protected]');
dictionary.set('ccc', '[email protected]');
console.log(dictionary.hasKey('aaa'));
console.log(dictionary.size());
console.log(dictionary.keys());
console.log(dictionary.values());
console.log(dictionary.get('bbb'));
dictionary.remove('bbb');
console.log(dictionary.keys());
console.log(dictionary.values());
console.log(dictionary.keyValues());
dictionary.forEach((k, v) => {
console.log('forEach:', `key: ${
k}, value: ${
v}`);
});