# Hash
# Description
创建一个散列对象,用作缓存
Hash {
__data__: [Object: null prototype] { a: 'a-value', b: 'b-value', c: 'c-value' },
size: 3
}
# Params
{Array} [entries] -- 要缓存的键值对
# Code
const HASH_UNDEFINED = '__lodash_hash_undefined__'
class Hash {
/**
* Creates a hash object.
*
* @private
* @constructor
* @param {Array} [entries] The key-value pairs to cache.
*/
constructor(entries) {
let index = -1
const length = entries == null ? 0 : entries.length
this.clear()
while (++index < length) {
const entry = entries[index]
this.set(entry[0], entry[1])
}
}
/**
* Removes all key-value entries from the hash.
*
* @memberOf Hash
*/
clear() {
this.__data__ = Object.create(null)
this.size = 0
}
/**
* Removes `key` and its value from the hash.
*
* @memberOf Hash
* @param {string} key The key of the value to remove.
* @returns {boolean} Returns `true` if the entry was removed, else `false`.
*/
delete(key) {
const result = this.has(key) && delete this.__data__[key]
this.size -= result ? 1 : 0
return result
}
/**
* Gets the hash value for `key`.
*
* @memberOf Hash
* @param {string} key The key of the value to get.
* @returns {*} Returns the entry value.
*/
get(key) {
const data = this.__data__
const result = data[key]
return result === HASH_UNDEFINED ? undefined : result
}
/**
* Checks if a hash value for `key` exists.
*
* @memberOf Hash
* @param {string} key The key of the entry to check.
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
*/
has(key) {
const data = this.__data__
return data[key] !== undefined
}
/**
* Sets the hash `key` to `value`.
*
* @memberOf Hash
* @param {string} key The key of the value to set.
* @param {*} value The value to set.
* @returns {Object} Returns the hash instance.
*/
set(key, value) {
const data = this.__data__
this.size += this.has(key) ? 0 : 1
data[key] = value === undefined ? HASH_UNDEFINED : value
return this
}
}
# Analyze
Hash 作为一个缓存 键值对的类 ,其数据结构如图所示, 返回的数据结构为
Hash {
__data__: [Object: null prototype] { a: 'a-value', b: 'b-value', c: 'c-value' },
size: 3
}
提供了 get set delete clear has 5个方法
# constructor
- 首先传入一个 键值对数组 ,拿到
length(对于一个对象可以通过Object.entries()生成键值对数组) - 调用
clear进行值的初始化 - 因为
index定义为-1,所以使用++index < length,while循环进行数据的缓存 - 拿到对应下标的值,通过
set方法进行数据的存储
# get
- 通过传入的
key拿到对应的值 - 如果获取到的结果为 默认未定义(
__lodash_hash_undefined__),则返回 undefined, 否则返回对应的值
# delete
从列表缓存中移除 key 及其值,成功返回 true 并更新 size ,失败返回 false
- 通过
has判断key是否存在于__data__中,如果存在则调用delete 操作符进行删除 - 根据
has或者delete的结果 更新size属性,成功-1, 失败-0 - 成功返回
true,失败返回false
# set
通过 key value 设置键值对,并且维护更新 size 属性
- 根据
has判断key值是否存在,决定size属性的值是否要更新,存在+0, 不存在+1 - 判断 传入的 value 是否 恒等于 undefined(这里可以传入 null),如果未定义,则将
value设置为默认未定义(__lodash_hash_undefined__),否则 设置为传入的值
# has
判断 __data__ 中是否存在对应的 key ,存在返回 true ,不存在返回 false
这里使用 data[key] !== undefined 来判断,是因为 在对象中,如果 key 值没有value,就会返回 undefined,但是 Hash 中,将 undefined 转换为了 __lodash_hash_undefined__,所以可以用此来判断 key 值是否存在
# clear
更新 __data__ 为新创的一个原型为 null 的空对象,因此并没有传统对象原型上的各种属性,并更新 size 属性,clear 也被用在初始化数据的过程中
# Remark
- delete 操作符 MDN (opens new window)
- Object.create() MDN (opens new window)
- 对象和属性 MDN (opens new window)
# Example
const obj = {'A': 'A-value', 'B': 'B-value', 'C': 'C-value'}
/**
* Hash {
* __data__: [Object: null prototype] {
* A: 'A-value',
* B: 'B-value',
* C: 'C-value',
* },
* size: 3
* }
*
*/
const temp = new Hash(Object.entries(obj))
temp.has('A') // true
/**
* Hash {
* __data__: [Object: null prototype] {
* A: 'A-value',
* B: 'B-value',
* C: 'C-value',
* D: 'D-value',
* },
* size: 4
* }
*
*/
temp.set('D', 'D-value')
temp.get('C') // C-value
/**
* Hash {
* __data__: [Object: null prototype] {
* A: 'A-value',
* C: 'C-value',
* D: 'D-value',
* },
* size: 4
* }
*
*/
temp.delete('B')
// Hash { __data__: [Object: null prototype] {}, size: 0 }
temp.clear()