# ListCache
# Description
创建一个列表缓存对象
# Params
{Array} [entries] -- 要缓存的键值对
# Depend
import assocIndexOf from './assocIndexOf.js'
# Code
class ListCache {
/**
* Creates an list cache 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 list cache.
*
* @memberOf ListCache
*/
clear() {
this.__data__ = []
this.size = 0
}
/**
* Removes `key` and its value from the list cache.
*
* @memberOf ListCache
* @param {string} key The key of the value to remove.
* @returns {boolean} Returns `true` if the entry was removed, else `false`.
*/
delete(key) {
const data = this.__data__
const index = assocIndexOf(data, key)
if (index < 0) {
return false
}
const lastIndex = data.length - 1
if (index == lastIndex) {
data.pop()
} else {
data.splice(index, 1)
}
--this.size
return true
}
/**
* Gets the list cache value for `key`.
*
* @memberOf ListCache
* @param {string} key The key of the value to get.
* @returns {*} Returns the entry value.
*/
get(key) {
const data = this.__data__
const index = assocIndexOf(data, key)
return index < 0 ? undefined : data[index][1]
}
/**
* Checks if a list cache value for `key` exists.
*
* @memberOf ListCache
* @param {string} key The key of the entry to check.
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
*/
has(key) {
return assocIndexOf(this.__data__, key) > -1
}
/**
* Sets the list cache `key` to `value`.
*
* @memberOf ListCache
* @param {string} key The key of the value to set.
* @param {*} value The value to set.
* @returns {Object} Returns the list cache instance.
*/
set(key, value) {
const data = this.__data__
const index = assocIndexOf(data, key)
if (index < 0) {
++this.size
data.push([key, value])
} else {
data[index][1] = value
}
return this
}
}
# Analyze
ListCache 作为一个缓存 键值对的类 ,其数据结构如图所示, 返回的数据结构为
{
__data__: [
['0', 'test1'],
['1', 'test2'],
],
size: 2
}
提供了 get set delete clear has 5个方法
# constructor
- 首先传入一个 键值对数组 ,拿到
length(对于一个对象可以通过Object.entries()生成键值对数组) - 调用
clear进行值的初始化 - 因为
index定义为-1,所以使用++index < length,while循环进行数据的缓存 - 拿到对应下标的值,通过
set方法进行数据的存储
# get
通过 key 值拿到对应的 value, 传入 key 值, 通过 assocIndexOf 方法来获取 key 值对应的下标(如果找不到返回-1),找到了下标则获取 data[index][1],否则返回 undefined
# delete
从列表缓存中移除' key '及其值,成功返回 true 并更新 size ,失败返回 false
- 通过
assocIndexOf拿到index - 如果没有找到(
index === -1),则返回false - 如果 index === length-1 ,则使用 pop 删除,否则使用 splice 删除,更新 size 属性,并返回 true
- 在这里最后一个元素 使用 pop 不使用 splice 是因为性能问题
splice 
shift 
pop 
由上图可以看出,shift pop 对比 splice 做的事情更少,判断逻辑更少,所以对于 delete 方法,在处理 第一项时,也可以使用 shift
# set
通过 key value 设置键值对,并且维护更新 size 属性
- 通过
assocIndexOf查询当前__data__中是否含有 对应的key - 如果不存在对应的
key,则更新size属性,并进行push - 如果存在对应的
key,则更新key对应的value值
# has
判断 __data__ 中是否存在对应的 key ,存在返回 true ,不存在返回 false
调用 assocIndexOf 来查找key,如果找不到 则返回 -1,所以这里使用了 > -1 来判断
# clear
从列表缓存中删除所有键值项,并更新 size 属性,clear 也被用在初始化数据的过程中
# Remark
- Object.entries() MDN (opens new window)
- Array.prototype.splice() MDN (opens new window)
- Array.prototype.shift() MDN (opens new window)
- Array.prototype.pop() MDN (opens new window)
- Array.prototype.push() MDN (opens new window)
# Example
const obj = {0: 'test1', 1: 'test2', 2: 'test3'}
/**
* ListCache {
* __data__: [ [ '0', 'test1' ], [ '1', 'test2' ], [ '2', 'test3' ] ],
* size: 3
* }
*/
const temp = new ListCache(Object.entries(obj))
temp.has(0) // false
temp.has('0') // true
/**
* ListCache {
* __data__: [
* [ '0', 'test1' ],
* [ '1', 'test2' ],
* [ '2', 'test3' ],
* [ '3', 'test4' ]
* ],
* size: 4
* }
*/
temp.set('3', 'test4')
temp.get('2') // test3
/**
* ListCache {
* __data__: [
* [ '0', 'test1' ],
* [ '2', 'test3' ],
* [ '3', 'test4' ]
* ],
* size: 4
* }
*/
temp.delete('1') // true
// ListCache { __data__: [], size: 0 }
temp.clear()