ES6中新增的数据结构Set、Map

Set对象,类似数组

Set类型数组,但是成员的值都是唯一的,Set内的元素是强类型,会进行类型检查。Set是一种叫做集合的数据结构

  • 集合是由一组无序且唯一(即不能重复)的项组成的,可以想象成集合是一个既没有重复元素,也没有顺序概念的数组
  • ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值
  • Set 本身是一个构造函数,用来生成 Set 数据结构

    Set实例的属性和方法

    Set的属性

  • size:返回集合所包含元素的数量

    Set的方法

  • 操作方法

    • add(value):向集合添加一个新的项
    • delete(value):从集合中移除一个值
    • has(value):如果值在集合中存在,返回true,否则false
    • clear(): 移除集合里所有的项
  • 遍历方法

    • keys():返回一个包含集合中所有键的数组
    • values():返回一个包含集合中所有值的数组
    • entries:返回一个包含集合中所有键值对的数组
    • forEach():用于对集合所有成员执行某种操作,没有返回值
      1. // 创建Set,提供一个Array作为输入,或者直接创建空Set
      2. let s = new Set();
      3. let s1 = new Set([1,2,"1","a",2,8])
      4. console.log(s1) // Set(5) {1, 2, "1", "a", 8}

      Set方法的原理实现

      创建一个Set对象
      1. function Set(arr = []){
      2. let items = {};
      3. this.size = 0;
      4. }
      5. module.exports = Set;

      has方法

      首先实现has方法,该方法会在后边几个方法中被使用到 ```javascript function Set(arr = []){ let items = {}; this.size = 0;

    this.has = function(val){ //判断对象是否拥有特定属性,使用hasOwnProperty方法 return items.hasOwnProperty(val) } } module.exports = Set; ```

    add方法

    对于给定的val,检测是否存在于集合中

  • 如果不存在,就添加到集合

  • 如果存在,返回false,不做任何操作

    1. this.add = function(val){
    2. if(!this.has(val)){
    3. items[val] = val;
    4. this.size++;
    5. return true;
    6. }
    7. return false;
    8. }

    delete和clear方法

    delete方法先判断val是否存在Set中,如果存在直接从Set中删除,返回true

    1. // delete方法
    2. this.delete = function(val){
    3. if(this.has(val)){
    4. delete items[val];
    5. this.size--;
    6. return true;
    7. }
    8. return false;
    9. }
    10. // clear方法
    11. this.clear = function(){
    12. items = {};
    13. this.size = 0;
    14. }

    keys和values方法

    1. //遍历key和value
    2. this.keys = function(){
    3. return Object.keys(items);
    4. }
    5. this.values = function(){
    6. return Object.values(items);
    7. }

    union并集

    1. //union并集
    2. this.union = function(other){
    3. let union = new Set()
    4. let values = this.values;
    5. for(let i=0;i<values.length;i++){
    6. union.add(values[i])
    7. }
    8. values = other.values(); // 将另一个set的value值重新赋值给values
    9. for(let j=0;j<values.length;j++){
    10. union.add(values[i])
    11. }
    12. return union;
    13. }

    intersect交集

    1. this.intersect = function(other){
    2. let intersect = new Set();
    3. let values =this.values;
    4. for(let i=0;i<values.length;i++){
    5. if(other.has(values[i])){
    6. intersect.add(values[i])
    7. }
    8. }
    9. return intersect;
    10. }

    difference差集

    差集的意思是:集合A和集合B的差集,表示A-B集合;前面集合减去后边集合的元素

    1. this.difference = function(other){
    2. let difference = new Set()
    3. let values = this.values()
    4. for(let i=0; i<values.length;i++){
    5. if(!other.has(value[i])){
    6. difference.add(values[i])
    7. }
    8. }
    9. return difference;
    10. }

    Set的完整代码

    1. function Set(arr = []){
    2. let items = {};
    3. this.size = 0;
    4. //has方法
    5. this.has = function(val){
    6. //判断对象是否拥有特定属性,使用hasOwnProperty方法
    7. return items.hasOwnProperty(val)
    8. }
    9. // add方法
    10. this.add = function(val){
    11. if(!this.has(val)){
    12. items[val] = val;
    13. this.size++;
    14. return true;
    15. }
    16. return false;
    17. }
    18. arr.forEach((val,i)=>{
    19. this.add(val);
    20. })
    21. // delete方法
    22. this.delete = function(val){
    23. if(this.has(val)){
    24. delete items[val];
    25. this.size--;
    26. return true;
    27. }
    28. return false;
    29. }
    30. // clear方法
    31. this.clear = function(){
    32. items = {};
    33. this.size = 0;
    34. }
    35. //遍历key和value
    36. this.keys = function(){
    37. return Object.keys(items);
    38. }
    39. this.values = function(){
    40. return Object.values(items);
    41. }
    42. //union并集
    43. this.union = function(other){
    44. let union = new Set()
    45. let values = this.values;
    46. for(let i=0;i<values.length;i++){
    47. union.add(values[i])
    48. }
    49. values = other.values(); // 将另一个set的value值重新赋值给values
    50. for(let j=0;j<values.length;j++){
    51. union.add(values[i])
    52. }
    53. return union;
    54. }
    55. // 交集
    56. this.intersect = function(other){
    57. let intersect = new Set();
    58. let values =this.values;
    59. for(let i=0;i<values.length;i++){
    60. if(other.has(values[i])){
    61. intersect.add(values[i])
    62. }
    63. }
    64. return intersect;
    65. }
    66. // 差集
    67. this.difference = function(other){
    68. let difference = new Set()
    69. let values = this.values()
    70. for(let i=0; i<values.length;i++){
    71. if(!other.has(value[i])){
    72. difference.add(values[i])
    73. }
    74. }
    75. return difference;
    76. }
    77. }
    78. module.exports = Set;

    测试

    1. const Set = require("./set.js");
    2. let set = new Set();
    3. set.add(1);
    4. set.add(2);
    5. set.add(3);
    6. console.log(set.size, set.keys());
    7. set.delete(2)
    8. console.log(set.values());
    9. set.clear();

    使用Set处理并集(Union)、交集(Intersect)、差集(Difference)

    1. let a = new Set([1,2,3])
    2. let b = new set([2,3,4])

    并集Union

    1. let union = new Set([...a, ...b]);
    2. console.log(union) // Set{1,2,3,4}

    交集Intersect

    1. let intersect = new Set([...a].filter(x=> b.has(x)))
    2. console.log(intersect) // Set {2,3}

    差集difference

    1. // a相对b的差集
    2. let defference = new Set([...a].filter(x => !b.has(x)))
    3. console.log(defference) // Set {1}

    Map对象

    Map类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

  • 键值对结构

  • 极快速查找

Set和Map的区别:

  • 共同点:
  • 不同点:

    Map对象的属性和方法

    属性:

  • size:返回Map所包含的元素个数

    操作方法

  • set(key,val)

  • get(key)
  • has(key)
  • delete(key)
  • clear()

    遍历方法

  • keys():

  • values():
  • forEach():
    1. // 创建Map
    2. const map = new Map([
    3. ['name', 'sammy'],
    4. ['title', 'author']
    5. ])
    6. map.size //2 size 是属性,不是函数
    7. map.has('name')
    8. map.get('name')

    Map方法的原理实现

    创建一个Map对象
    1. function Map(){
    2. let items = {}
    3. }
    4. modules.exports = Map;

    has方法

    1. function Map(){
    2. let items = {};
    3. this.has = function(){
    4. return items.hasOwnProperty(val)
    5. }
    6. }

    set和get方法

    1. // set(key, val)
    2. // set相同key,后面声明的会覆盖前面的值
    3. this.set = function(key, val){
    4. item[key] = val;
    5. }
    6. // get(key)
    7. this.get = function(key){
    8. // 判断是否有key,如果有,直接返回对应的值
    9. // 如果么有,返回undefined
    10. return this.has(key) ? items[key] : undefined;
    11. }

    delete和clear方法

    1. this.delete = function(key){
    2. if(this.has(key)){
    3. delete items[key];
    4. this.size--;
    5. return true
    6. }
    7. return false;
    8. }
    9. this.clear = function(){
    10. items = {};
    11. this.size = 0;
    12. }

    遍历方法keys/values/forEach

    ```javascript this.keys = function(){ return Object.keys(items) }

this.values = function(){ return Object.values(items) }

this.forEach= function(fn, context=this){ for(let i=0;i<this.size;i++){ let key = Object.keys(items)[i]; let value = Object.values(items)[i]; fn.call(context, value, key, items); } }

  1. <a name="Mzpa4"></a>
  2. ### Map的完整实现代码
  3. ```javascript
  4. function Map() {
  5. let items = {};
  6. this.size = 0;
  7. // 操作方法
  8. // has方法
  9. this.has = function(val) {
  10. return items.hasOwnProperty(val);
  11. };
  12. // set(key, val)方法
  13. this.set = function(key, val) {
  14. items[key] = val;
  15. this.size++;
  16. };
  17. // get(key)方法
  18. this.get = function(key) {
  19. return this.has(key) ? items[key] : undefined;
  20. };
  21. // delete(key)方法
  22. this.delete = function(key) {
  23. if (this.has(key)) {
  24. delete items[key];
  25. this.size--;
  26. return true;
  27. }
  28. return false;
  29. };
  30. // clear()方法
  31. this.clear = function() {
  32. items = {};
  33. this.size = 0;
  34. };
  35. // 遍历方法
  36. // keys()方法
  37. this.keys = function() {
  38. return Object.keys(items);
  39. };
  40. // values()方法
  41. this.values = function() {
  42. return Object.values(items);
  43. };
  44. // forEach(fn, context)方法
  45. this.forEach = function(fn, context = this) {
  46. for (let i = 0; i < this.size; i++) {
  47. let key = Object.keys(items)[i];
  48. let value = Object.values(items)[i];
  49. fn.call(context, value, key, items);
  50. }
  51. };
  52. }
  53. module.exports = Map;

测试

  1. const Map = require('./Map.js')
  2. let m = new Map();
  3. m.set("name","map object")
  4. let o = new Object()
  5. m.set(o, "object");
  6. console.log(m.size, m.keys(), m.values(), m.get(o))
  7. m.delete("name")

Map to Array

  1. let map1 = new Map()
  2. .set(true, 8)
  3. .set({foo:3}, ['aaa'])
  4. console.log([...map1]) // [[true,7], [{foo:3}, ['aaa']]]

Array to Map

  1. let arr = [[true,7], [{foo:3}, ['abc']]]
  2. let map2 = new Map(arr)
  3. console.log(map2)
  4. // Map{
  5. // true => 7,
  6. // Object {foo:3} => ['aaa']
  7. // }

Map to Object

  1. function strMapToObj(strMap) {
  2. let obj = Object.create(null);
  3. // for in 获取的key
  4. // for of 获取的value
  5. for (let [k,v] of strMap) {
  6. obj[k] = v;
  7. }
  8. return obj;
  9. }
  10. const map3= new Map()
  11. .set("yes",true)
  12. .set("no", false)
  13. strMapToObj(map3) // { yes: true, no: false }

Object To Map

  1. function objToStrMap(obj){
  2. return new Map(Object.entries(obj))
  3. }
  4. let obj = {"a":1, "b":2}
  5. console.log(objToStrmap(obj))

Map to JSON

  1. function strMapToJson(strMap) {
  2. // 先将Map转为Object,然后在转为JSON
  3. return JSON.stringify(strMapToObj(strMap));
  4. }
  5. let myMap = new Map().set('yes', true).set('no', false);
  6. strMapToJson(myMap)
  7. // '{"yes":true,"no":false}'

JSON to Map

  1. function jsonToStrMap(jsonStr) {
  2. return objToStrMap(JSON.parse(jsonStr));
  3. }
  4. jsonToStrMap('{"yes": true, "no": false}')
  5. // Map {'yes' => true, 'no' => false}

WeakSet和WeakMap对象

WeakSet && WeakMap 所引用的对象都是弱引用,即垃圾回收机制不将该引用考虑在内。因此,只要所引用的对象的其他引用都被清除,垃圾回收机制就会释放该对象所占用的内存。也就是说,一旦不再需要,WeakSet && WeakMap 里面的键名对象和所对应的键值对会自动消失,不用手动删除引用。

链接:https://juejin.im/post/6883014651110506510