In the little garden of dreams, I keep the misty rain of the whole season for you.

— Love, Spirit River

Welcome to Star: Pocket-LoDash

Gitbook will also be updated with the warehouse. Gitbook address: Pocket-Lodash

Function and Usage

A Hash, as its name implies, is a discrete sequence that stores data based on keys. In javascript, the best place to start is with objects.

Hash is used as an internal file in the.internal folder of Lodash. Lodash selects different caching methods based on different data types, and Hash is one of them. This method can only cache data of the key type that meets the requirements of the object key.

Hash takes only a two-dimensional array as an argument and is called as follows:

new Hash([['tes1'.1], ['test2'.2], ['test3'.3]])
Copy the code

The first item in the subitem is the key, and the second item is the value to cache.

The result of the Hash instantiation is as follows:

{
  size: 3.__data__: {
    test1: 1.test2: 2.test3: 3}}Copy the code

The amount of cache is stored in the __data__ object.

Hash with the Map

In addition to using Hash to cache data, Map is also used. Lodash designs the Hash data management interface in accordance with the Map interface, but does not include Map traversal method.

Let’s take a look at what these interfaces have:

The source code

const HASH_UNDEFINED = '__lodash_hash_undefined__'

class Hash {
  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])
    }
  }
  clear() {
    this.__data__ = Object.create(null)
    this.size = 0
  }
  delete(key) {
    const result = this.has(key) && delete this.__data__[key]
    this.size -= result ? 1 : 0
    return result
  }
  get(key) {
    const data = this.__data__
    const result = data[key]
    return result === HASH_UNDEFINED ? undefined : result
  }
  has(key) {
    const data = this.__data__
    returndata[key] ! = =undefined
  }
  set(key, value) {
    const data = this.__data__
    this.size += this.has(key) ? 0 : 1
    data[key] = value === undefined ? HASH_UNDEFINED : value
    return this}}export default Hash
Copy the code

constructor

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])}}Copy the code

The __data__ and size attributes are not initialized in constructor, which are actually initialized in the clear method, as explained below.

We then iterate over the incoming two-dimensional array and call the set method to initialize the cached value. The first item of the subitem is the key and the second item is the cached value.

clear

clear() {
  this.__data__ = Object.create(null)
  this.size = 0
}
Copy the code

Clear clears the cache, so you need to reset size to 0.

Sets the cached data __data__ to an empty object.

Instead of this.__data__ = {} being null, the Object.create method is called and null is taken as an argument. When null is passed to the Object, it returns a vacuum Object. This is an Object with no prototype, so there is no interference from the prototype attributes.

has

has(key) {
  const data = this.__data__
  returndata[key] ! = =undefined
}
Copy the code

Has determines whether cached data already exists, and returns true if the cached data already exists.

The judgment is also very simple, just need to determine whether the value is undefined.

There’s a catch in this judgment, which we’ll talk about later.

set

set(key, value) {
  const data = this.__data__
  this.size += this.has(key) ? 0 : 1
  data[key] = value === undefined ? HASH_UNDEFINED : value
  return this
}
Copy the code

Set is used to increment or update values that need to be cached. When setting, you need to maintain both the size and the cached value.

The has method is called to determine whether the corresponding key has been cached. If it has been cached, size remains the same; otherwise, size is increased by 1.

The cache value is the value of the key property corresponding to the cache object this.__data__.

In has talking about using data[key]! == undefined has a pit, because the value to cache can also be undefined, if not done, will definitely cause errors.

Lodash handles this by converting the value of undefined to HASH_UNDEFINED, which is the __lodash_hash_undefined__ string defined from the start.

So in the cache, undefined is replaced by the string __lodash_hash_undefined__.

Set also returns an instance of this at the end to support chained operations.

get

get(key) {
  const data = this.__data__
  const result = data[key]
  return result === HASH_UNDEFINED ? undefined : result
}
Copy the code

The get method takes the value from the cache.

The value of the key in the cache object is returned. Because undefined is represented in the cache as __lodash_hash_undefined__, undefined is returned when a value of __lodash_hash_undefined__ is encountered.

There is a slight problem with this. If the value that needs to be cached happens to be __lodash_hash_undefined__, the retrieved value will not match the default value. But that’s not often the case.

delete

delete(key) {
  const result = this.has(key) && delete this.__data__[key]
  this.size -= result ? 1 : 0
  return result
}
Copy the code

The delete method is used to delete the cache for the specified key. Returns true on success, false otherwise. The delete operation also maintains the size attribute and cache value.

The has method is first called to determine whether the cache exists, and if so, the corresponding attribute in __data__ is removed with the delete operator.

The delete operator returns true when the attribute is successfully deleted, and if it is successfully deleted, you need to reduce size by 1.

reference

  1. Set and Map data structures
  2. Object.create()

License

CC BY-NC-ND 4.0

Finally, all articles will be simultaneously sent to the wechat public account, welcome to pay attention to, welcome to comment:

Akik The opposite corner