Es6 - Set & Map

43 阅读4分钟

1、Set

特性
  • ES6 提供了新的数据结构 Set
  • 成员的值都是唯一的
属性和方法
  • 属性
    • Set.prototype.size:返回Set实例的成员总数
  • 方法
    • 操作方法(用于操作数据)
      • Set.prototype.has(value):返回一个布尔值,表示该值是否为Set的成员
      • Set.prototype.add(value):添加某个值,返回 Set 结构本身
      • Set.prototype.delete(value):删除某个值,返回一个布尔值,表示删除是否成功
      • Set.prototype.clear():清除所有成员,没有返回值
    • 遍历方法:key和value是一样的( keys()和values()返回结果相同 )
      • Set.prototype.keys():返回键名遍历器
      • Set.prototype.values():返回键值遍历器
      • Set.prototype.entries():返回键值对遍历器
      • Set.prototype.forEach():使用回调函数遍历每个成员
应用场景
// 数组去重 
let temp = [...(new Set(arr))]

2、WeakSet

特性
  • WeakSet 的成员 只能是对象,而不能是其他类型的值
  • WeakSet 中的对象都是弱引用
    • 通常情况,如果一个对象没有任何引用,那么此对象会尽快被垃圾回收
    • 即垃圾回收机制 不考虑 WeakSet 对该对象的引用 ( 不被其他引用则被回收 )
    • 也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中
  • WeakSet 没有size属性,没法遍历(故没有 forEach 方法)
    • 因为 WeakSet 中有多少个成员取决于(没有其他对象对WeakSet成员的引用后)垃圾回收机制有没有运行,运行前后可能成员的个数是不一样的,而垃圾回收机制何时运行是不可预测的,所以 ES6 规定 WeakSet 不能被遍历
方法
  • 操作方法(用于操作数据)
    • WeakSet.prototype.add(value):向 WeakSet 实例添加一个新成员
    • WeakSet.prototype.delete(value):清除 WeakSet 实例的指定成员
    • WeakSet.prototype.has(value):返回布尔值,表示某个值是否在WeakSet 实例之中
使用场景
  • 用于存储DOM节点,而不用担心这些节点从文档移除时会引发内存泄露
let div = document.querySelector("div");
let set = new Set();
set.add(div);
//...some code
document.body.removeChild(div);
div = null; //dom对象仍在内存中,因为Set中仍然引用此对象

let div = document.querySelector("div");
let weakset = new WeakSet();
weakset.add(div);
//...some code
document.body.removeChild(div);
div = null; //dom对象的已经没有引用,将被垃圾回收机制回收

3、Map

特性
  • JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构)
  • 传统上只能用字符串当作键
  • 为了解决这个问题,ES6 提供了 Map 数据结构
  • 类似于对象,也是键值对的集合,但是 “键” 的范围不限于字符串,各种类型的值
属性和方法
  • 属性
    • Map.prototype.size:返回Map实例的成员总数
  • 方法
    • 操作方法(用于操作数据)
      • Map.prototype.get(key):读取key对应的键值,如果找不到key,返回undefined
      • Map.prototype.set(key,value):设置键名key对应的键值为value
      • Map.prototype.has(key):返回一个布尔值
      • Map.prototype.delete(key):删除某个键,返回true。如果删除失败,返回false。
      • Map.prototype.clear():清除所有成员,没有返回值
    • 遍历方法:
      • Map.prototype.keys():返回键名遍历器
      • Map.prototype.values():返回键值遍历器
      • Map.prototype.entries():返回键值对遍历器
      • Map.prototype.forEach():使用回调函数遍历每个成员
应用场景

私有属性的封装

var Person = (function () {
  var map = new Map();

  function Person(name, age) {
    var privateProperty = {
      name: name,
      age: age,
    };
    map.set(this, privateProperty);
  }

  Person.prototype.getName = function () {
    return map.get(this).name;
  };

  Person.prototype.getAge = function () {
    return map.get(this).age;
  };
  return Person;
})();

let zs = new Person("zs");
let ls = new Person("ls");

4、WeakMap

特性
  • WeakMap 的键只能是对象,而不能是其他类型的值。
  • WeakMap 中对键的引用是弱引用,不能遍历、健随时可消失
  • WeakMap 弱引用的只是键名,而不是键值。键值依然是正常引用
方法
  • 没有size属性,没法遍历(故没有 forEach 方法)
  • 操作方法(用于操作数据)
    • WeakMap.prototype.set(key,value):设置键名key对应的键值为value
    • WeakMap.prototype.get(key):读取key对应的键值,如果找不到key,返回undefined
    • WeakMap.prototype.has(key):返回一个布尔值
    • WeakMap.prototype.delete(key):删除某个键,返回true。如果删除失败,返回false
应用场景

私有属性的封装

var Person = (function () {
  var map = new WeakMap();

  function Person(name, age) {
    var privateProperty = {
      name: name,
      age: age,
    };
    map.set(this, privateProperty);
  }

  Person.prototype.getName = function () {
    return map.get(this).name;
  };

  Person.prototype.getAge = function () {
    return map.get(this).age;
  };
  return Person;
})();

let zs = new Person("zs");
let ls = new Person("ls");
zs = null; // 键是弱引用
ls = null; // 键是弱引用

5、弱引用与强引用的解释说明

删除引用,内存移出

// obj是引用,对象可用
let obj = { id: 1 };

// 对象从内存移除
obj = null; // 重写引用

重写obj,对象依然会存在于内存中 ( 被对象、数组强引用 )

let obj = { id: 1 };
const arr = [obj];
const user = { info: obj };
const set = new Set([obj]);
const map = new Map([[obj, "info"]]);
obj = null; // 释放obj

console.log("arr", arr);
console.log("user", user);
console.log("set", set);
console.log("map", map); // 无法知道垃圾回收机制什么时候执行