JavaScript Map 对象

750 阅读3分钟

前言

记一次 Map 对象的使用

简介

ES6 提供了 Map 数据结构。它类似对象,是键值对的集合。

  • Map 对象保存键值对,并且能够记住键的原始插入顺序。

  • 任何值(对象或者原始值)都可以作为一个键或一个值。

  • 具有 size 属性。

属性
  • size 用于返回 一个 Map 对象的成员数量
const initMap = new Map([
    ['forever', 'you know you love me'],
    ['luckdog', 'that is interesting'],
])

// Map 构造函数接受数组作为参数,实际上执行的是👇
const list = [
    ['name', 'zhangsan'],
    ['age', 26]
];

const newMap = new Map();

list.forEach(([key, value]) => newMap.set(key, value));

console.log(initMap.size, 'initMap.size');  // 2
console.log(newMap.size, 'newMap.size');  // 2
基本方法
  • new Map() 创建一个新的 Map 对象。

  • set() 为 Map 对象中添加或更新一个指定了键(key)的值(value)。返回 Map 对象。

  • get() 获取 Map 对象中指定键的值。若找不到,返回undefined

  • keys() 返回一个引用的 Iterator 对象。它包含按照顺序插入 Map 中每个元素的 key 值。

  • values() 同 keys(),返回 value 值。

  • entries() 返回自身所有成员。


const testMap = new Map();

testMap.set('forever', 'you know you love me');
testMap.set('luckdog', 'that is interesting');

// Map(2) {'forever' => 'you know you love me', 'luckdog' => 'that is interesting'}
console.log(testMap, 'testMap');

testMap.get('forever'); // 'you know you love me'

// MapIterator {'forever', 'luckdog'}
const mapKeys =  testMap.keys(); 

// MapIterator {'you know you love me', 'that is interesting'}
const mapValues = testMap.values(); 

// 可以通过 扩展运算符 将 Map 结构快速转为数组结构
[...mapKeys]
[...mapValues]

注意: 如果 Map 的键是基本类型(数字、字符串、布尔值),则只要两个值严格相等,Map 将其视为一个键。另外undefinednull是两个不同的键。Map 将NaN视为同一个键。

// eg:
const testMap = new Map();

testMap.set(+0, 0);
testMap.get(-0); // 0

testMap.set(true, 1);
testMap.get('true'); // undefined

testMap.set(undefined, 1);
testMap.set(null, 2);
testMap.get(undefined); // 1
testMap.get(null); // 2

testMap.set(NaN, 1);
testMap.get(NaN); // 1
其他方法
  • has() 返回布尔值,用来表明 Map 中是否存在指定元素。

  • delete() 删除 Map 对象中指定元素,返回true。删除失败则返回false

  • clear() 移除 Map 对象中所有元素。无返回值。

  • forEach() 与数组方法类似,可实现遍历。


const testMap = new Map()

testMap.set('name', 'liming');
testMap.set('age', 24);

testMap.forEach((value, key, map) => {
    console.log(value, key, map)
})

testMap.has('name'); // true

testMap.delete('age'); // true
testMap.delete('haha'); // false

testMap.clear(); // undefined
应用
  1. 写一个 LRU 缓存函数

LRU(Least Recently Used)算法是一种常见的页面置换算法,选择最近最久未使用的页面予以淘汰。

设计原理: 当数据在最近一段时间经常被访问,那么它在以后也会经常被访问。这意味着,如果经常访问的数据,我们需要其能够快速命中,而不常访问的数据,我们会在超出容量限制后,将其淘汰。

/**
 * @param {number} capacity 容量限制
 */
var LRUCache = function (capacity) {
  this.capacity = capacity; // 存储当前容量限制
  this.cache = new Map(); // 初始化 Map 对象,用于缓存
};

/** 
 * @param {number} key
 * @return {number} 存在则返回当前键(key)对应的值,否则返回 -1
 */
LRUCache.prototype.get = function (key) {
  // 如果关键字 key 不存在缓存中
  if (!this.cache.has(key)) {
    console.log(-1)
    return -1
  }

  // 获取关键字的值,删除并重新存储再尾部
  const value = this.cache.get(key)
  this.cache.delete(key);
  this.cache.set(key, value);
  console.log(value)
  return value
};

/** 
 * @param {number} key 
 * @param {number} value
 * @return {void}
 */
LRUCache.prototype.put = function (key, value) {
  if (this.cache.has(key)) {
    // 如果当前键(key)存在,则删除并重新存储到 Map 对象尾部
    this.cache.delete(key)
  } else if (this.cache.size >= this.capacity) {
    // 如果是新增操作,则删除 Map 第一个键值对(最早记录),并将新元素存储到 Map 对象尾部
    this.cache.delete(this.cache.keys().next().value);
  }
  this.cache.set(key, value);
};

/**
 * LRUCache 对象将被实例化和调用
 * const lruCache = new LRUCache(capacity);
 * const param_1 = lruCache.get(key);
 * lruCache.put(key, value);
 */
const lruCache = new LRUCache(2);

lruCache.put(1, 1);
lruCache.put(2, 2);

lruCache.get(1); // 1

lruCache.put(3, 3);

lruCache.get(2); // -1,表示未找到

lruCache.put(4, 4); // 该操作会使关键字 1 作废

lruCache.get(1); // -1

lruCache.get(3); // 3
lruCache.get(4); // 4

参考

最后


  • 文章是自己手敲,是对工作日常的总结,如有错误之处,敬请指正
  • 如果遇到什么问题就留言吧,能解决大家帮忙一起解决一下
  • 后续有问题的话会一直修改补充