• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

JavaScript 系列 - Map 和 WeakMap

武飞扬头像
neo_of_matrix
帮助5

Map

Map 对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者基本类型)都可以作为一个键或一个值。

使用

new Map([iterable])

特点

  • 在映射中用作键和值的对象及其他“集合”类型,在自己的内容或属性被修改时仍然保持不变
  • 内存地址不一样视为不同 key
    • 0、-0 相同
    • NaN 相同
  • Map 实例会维护键值对的插入顺序,因此可以根据插入顺序执行迭代操作

静态属性

Map[Symbol.species] 访问器属性会返回一个 Map 构造函数

class MyMap extends Map {
  // 重写覆盖 MyMap species to the parent Map constructor
  static get [Symbol.species]() {
    return Map;
  }
}

实例属性

Map.prototype.size

实例方法

  • Map.prototype.set(key, value)

    • 返回的是当前的 Map 对象
    • 链式调用
  • Map.prototype.get(key)

    如果找不到 key,返回 undefined

  • Map.prototype.has(key)

    返回一个布尔值

  • Map.prototype.delete(key)

    返回 true。如果删除失败,返回 false

  • Map.prototype.clear()

    没有返回值

  • Map.prototype[@@iterator]()

    const map1 = new Map();
    
    map1.set('0', 'foo');
    map1.set(1, 'bar');
    
    const iterator1 = map1[Symbol.iterator]();
    
    for (const item of iterator1) {
      console.log(item);
    }
    // Expected output: Array ["0", "foo"]
    // Expected output: Array [1, "bar"]
    
  • 遍历

    • Map.prototype.keys()
    • Map.prototype.values()
    • Map.prototype.entries()
    • Map.prototype.forEach(value, key)
    • 默认迭代器
      • map[Symbol.iterator] === map.entries

借用数组方法

  • new Map([...map].filter())
  • new Map([...map].map())

转换

  • Map 转为数组

    [...myMap]

  • 数组转为 Map

    new Map([])

  • Map 转为对象

    • 都是字符串,它可以无损地转为对象
    • 有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名
    • 遍历 Map 然后赋值给 object
    function strMapToObj(strMap) {
      let obj = Object.create(null);
      for (let [k, v] of strMap) {
        obj[k] = v;
      }
      return obj;
    }
    
  • 对象转为 Map

    • Object.entries
    let obj = { a: 1, b: 2 };
    let map = new Map(Object.entries(obj));
    function objToStrMap(obj) {
      let strMap = new Map();
      for (let k of Object.keys(obj)) {
        strMap.set(k, obj[k]);
      }
      return strMap;
    }
    
  • Map 转为 JSON

    • Map 的键名都是字符串,这时可以选择转为对象 JSON
    function strMapToJson(strMap) {
      return JSON.stringify(strMapToObj(strMap));
    }
    
    • Map 的键名有非字符串,这时可以选择转为 JSON 数组
    function mapToArrayJson(map) {
      return JSON.stringify([...map]);
    }
    
  • JSON 转为 Map

    • 所有键名都是字符串
    function jsonToStrMap(jsonStr) {
      return objToStrMap(JSON.parse(jsonStr));
    }
    
    • 整个 JSON 就是一个数组,且每个数组成员本身,又是一个有两个成员的数组
    function jsonToMap(jsonStr) {
      return new Map(JSON.parse(jsonStr));
    }
    

使用场景

  • 内存占用 Map
  • 插入性能 Map
  • 查找速度 Object
  • 删除性能 Map

Map 和 Object

  • 如果键在运行时才能知道,或者所有的键类型相同,所有的值类型相同,那就使用 Map
  • 如果需要将原始值存储为键,则使用 Map
  • 如果需要对个别元素进行操作,使用 Object

意外的键

  • Map 默认情况不包含任何键。只包含显式插入的键
  • 一个 Object 有一个原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突

键的类型

  • 一个 Map 的键可以是任意值,包括函数、对象或任意基本类型
  • 一个 Object 的键必须是一个 String 或是 Symbol

键的顺序

  • Map 中的键是有序的。因此,当迭代的时候,一个 Map 对象以插入的顺序返回键值
  • 虽然 Object 的键目前是有序的,但并不总是这样,而且这个顺序是复杂的。因此,最好不要依赖属性的顺序

Size

  • Map 的键值对个数可以轻易地通过 size 属性获取
  • Object 的键值对个数只能手动计算

迭代

  • Map 是可迭代的的,所以可以直接被迭代
  • Object 没有实现迭代协议,所以使用 JavaSctipt 的 for...of 表达式并不能直接迭代对象

性能

  • 在频繁增删键值对的场景下表现更好
  • 在频繁添加和删除键值对的场景下未作出优化

序列化和解析

  • Map 没有元素的序列化和解析的支持
  • 原生的由 Object 到 JSON 的序列化支持,使用 JSON.stringify(),原生的由 JSON 到 Object 的解析支持,使用 JSON.parse()

WeakMap

WeakMap 对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的。

实例方法

  • WeakMap.prototype.delete(key)
  • WeakMap.prototype.get(key)
  • WeakMap.prototype.has(key)
  • WeakMap.prototype.set(key, value)

特点

  • 只接受对象作为键名(null除外),不接受其他类型的值作为键名
  • 键名所指向的对象,不计入垃圾回收机制
  • 不能遍历操作

用途

DOM 节点作为键名

const m = new WeakMap();
const loginButton = document.querySelector("#login");
// Associates some metadata with the node
m.set(loginButton, { disabled: false });
loginButton.addEventListener(
  "click",
  function () {
    m.set(loginButton, { disabled: true });
  },
  false
);

部署私有属性

const User = (() => {
  const wm = new WeakMap();
  class User {
    constructor(id) {
      this.idProperty = Symbol("id");
      this.setId(id);
    }
    setPrivate(property, value) {
      const privateMembers = wm.get(this) || {};
      privateMembers[property] = value;
      wm.set(this, privateMembers);
    }
    getPrivate(property) {
      return wm.get(this)[property];
    }
    setId(id) {
      this.setPrivate(this.idProperty, id);
    }
    getId(id) {
      return this.getPrivate(this.idProperty);
    }
  }
  return User;
})();
const user = new User(123);
alert(user.getId()); // 123
user.setId(456);
alert(user.getId()); // 456

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfheehc
系列文章
更多 icon
同类精品
更多 icon
继续加载