• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
可爱熊
熊爱可
博客园    首页    新随笔    联系   管理    订阅  订阅

Set和Map数据结构

1. ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

 Set 本身是一个构造函数,用来生成 Set 数据结构。

 Set 函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。

 const set = new Set([1, 2, 3, 4, 4]);

 [...set]  // [1, 2, 3, 4]

 const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);

 items.size  // 5

 Set 内部判断两个值是否不同,使用的算法叫做“Same-value equality”,它类似于精确相等运算符(===),主要的区别是NaN等于自身,而精确相等运算符认为NaN不等于自身。

 Set内部NaN等于NaN

 let set = new Set();

 let  a = NaN;

 let  b = NaN;

 set.add(a);

    set.add(b);

 set   // {NaN}  只存在一个NaN, 说明Set内部的NaN是等于自身的

 Set内部两个对象是不相等的

 let set = new Set();

 set.add({});

 set.size  // 1

 set.add({})

 set.size  // 2

 四个操作方法

 add delete    has    clear

 let set = new Set()

 set.add(1)  set.delete(1)  set.has(1)  set.clear()

 Array.from方法可以将 Set 结构转为数组。

 const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);

 Array.from(items)  // [1, 2, 3, 4, 5]

    数组去重

    function dedupe(array) {
  return Array.from(new Set(array));
 }

 dedupe([1, 1, 2, 1, 1, 2, 2, 34, 5])   // [1, 2, 34, 5]

    forEach(): 对数组中的每一项执行某方法

    map(): 数组中的每一项执行某个函数并返回执行后结果的数组

2. 遍历

  Set内部使用for...of...循环,所以Set可以使用扩展运算符展开

  扩展运算符和 Set 结构相结合,就可以去除数组的重复成员。

  数组去重

  let set = [1, 2, 3, 2, 1];

  let unique = [...new Set(set)];

  unique   // [1, 2, 3]

  并集

  let a = new Set([1, 2, 3])

  let b = new Set([4, 3, 2])

  let union = new Set([...a, ...b])

  union  // Set(4)   {1, 2, 3, 4}

  [...union]  // [1, 2, 3, 4]

  交集

  let intersect = new Set([...a].filter(x => b.has(x)))

  intersect   // {2, 3}

  差集

  let difference = new Set([...a].filter(x => !b.has(x)))

  difference   // {1}

3. WeakSet

  WeakSet 结构与 Set 类似,也是不重复的值的集合。WeakSet 的成员只能是对象,而不能是其他类型的值。

  WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。

  ES6 规定 WeakSet 不可遍历。

  WeakSet 是一个构造函数,可以使用new命令,创建 WeakSet 数据结构。

  const ws = new WeakSet();

  作为构造函数,WeakSet 可以接受一个数组或类似数组的对象作为参数。(实际上,任何具有 Iterable 接口的对象,都可以作为 WeakSet 的参数。)该数组的所有成员,都会自动成为 WeakSet 实例对象的成员。

  const a = [[1, 2], [3, 4]];

  const ws = new WeakSet(a);

  ws  // [[1, 2], [3, 4]]

  const b = [3, 4];

  const ws = new WeakSet(b);  // Invalid value used in weak set

  上面报错是因为 数组逇成员是数组或类似数组的对象, 数组b的成员不是数组或类似数组的成员,而数组a的成员是数组或类似数组的对象。          

  WeakSet.prototype.add(value)  向WaekSet实例中添加一个新成员

  WeakSet.prototype.delete(value) 从WaekSet删除一个指定成员

  WeakSet.prototype.has(value) 返回一个布尔值, 判断一个值是否存在WeakSet实例中

  WeakSet 没有size属性,没有办法遍历它的成员。

  WeakSet 不能遍历,是因为成员都是弱引用,随时可能消失,遍历机制无法保证成员的存在,很可能刚刚遍历结束,成员就取不到了、

4. Map 

  const m = new Map();

  const o = {p: 'Hello world'};

  m.set(o, 'content');

  m.get(o);  // "content"

  m.has(o)  // true

  m.delete(o)  // true

  m.has(o)  // false

  作为构造函数,Map 也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。

  const map = new Map([
    ['name', '张三'],
    ['title', 'Author']
  ])

  map.size  // 2

  map.has('name')  // true

  map.get('name')  // 张三

  只有对同一个对象的引用,Map 结构才将其视为同一个键。

  const map = new Map();

  map.set(['a'], '555');  

  map.get(['a'])  // undefined

  Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。这就解决了同名属性碰撞(clash)的问题,我们扩展别人的库的时候,如果使用对象作为键名,就不用担心自己的属性与原作者的属性同名。

  Map 结构的实例有以下属性和操作方法。

  size属性: size属性返回 Map 结构的成员总数。

  const map = new Map();

  map.set('foo', true);

  map.set('bar', false);

  map.size  // 2

  map   // [['foo', true], ['bar', false]]

  set(value, key)

  map.set(1, 'one').set(2, 'second').set(3, 'third');  // 可以链式写

  get(key)

  get方法读取key对应的键值,如果找不到key,返回undefined。

  const m = new Map();

  const hello = function() {console.log('hello')}

  m.set(hello, 'hello es6')

  m.get(hello)  // "hello es6"

  has(key)  

  has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。

  const m = new Map();

  m.set('edition', 6);

  m.set(262, 'standard');

  m.set(undefined, 'nah');

  m.has('edition')  // true

  m.has('year')  // false

  delete(key)

  delete方法删除某个键,返回true。如果删除失败,返回false。

  m.delete(262)  // true

  m.delete(262)  // false  因为已经删除 262key 不存在 所以返回false

  clear()

  clear方法清除所有成员,没有返回值。

  Map 结构转为数组结构,比较快速的方法是使用扩展运算符(...)。

  const map = new Map([
    [1, 'one'],
    [2, 'two'],
    [3, 'three']
  ])

  [...map.keys()]  // [1, 2, 3]

  结合数组的map方法、filter方法,可以实现 Map 的遍历和过滤(Map 本身没有map和filter方法)。

  与其他数据结构的互相转换

  Map转为数组

  Map 转为数组最方便的方法,就是使用扩展运算符(...)。

  const myMap = new Map();

  myMap.set(true, 7).set({foo:3}, ['abc'])

  [...myMap]  // [[true, 7], [{foo:3}, ['abc']]]

  数组转为Map

  将数组传入 Map 构造函数,就可以转为 Map。

  let map = [...myMap];

  new Map(map)  // 数组转为Map 作为参数传给Map就可以将数组转为Map

  Map转为对象

  function strMapToObj(strMap) {
    let obj = Object.create(null);
    console.log(obj, 'obj');
    for (let [k,v] of strMap) {
      obj[k] = v;
    }
    return obj;
  }

  const myMap = new Map().set('yes', true).set('no', false);

  strMapToObj(myMap);  // {yes: true, no: false}

  对象转为Map

  function objToStrMap(obj) {
    let strMap = new Map();
    for (let k of Object.keys(obj)) {
      strMap.set(k, obj[k]);
    }
    return strMap;
  }

  objToStrMap({yes: true, no: false});  // {"yes" => true, "no" => false}

  Map转为JSON(对象JSON)

  Map 转为 JSON 要区分两种情况。一种情况是,Map 的键名都是字符串,这时可以选择转为对象 JSON。

  function strMapToObj(strMap) {
    let obj = Object.create(null);
    for (let [k,v] of strMap) {
      obj[k] = v;
    }
    return obj;
  }

  function strMapToJson(strMap) {
    return JSON.stringify(strMapToObj(strMap));
  }

  let myMap = new Map().set('yes', true).set('no', false);

  strMapToJson(myMap)  // "{"yes":true,"no":false}"

  Map转为JSON(数组JSON)

  function mapToArrayJson(map) {
    return JSON.stringify([...map]);
  }

  let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);

  mapToArrayJson(myMap)  // "[[true,7],[{"foo":3},["abc"]]]"

  JSON转为Map

  JSON 转为 Map,正常情况下,所有键名都是字符串

  function objToStrMap(obj) {
    let strMap = new Map();
    for (let k of Object.keys(obj)) {
      strMap.set(k, obj[k]);
    }
    return strMap;
  }

  function jsonToStrMap(jsonStr) {
    return objToStrMap(JSON.parse(jsonStr));
  }

  jsonToStrMap('{"yes": true, "no": false}')  // {yes: true, no: false}

5. WeakMap

  WeakMap结构与Map结构类似,也是用于生成键值对的集合。

  WeakMap与Map的区别有两点

  ①WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名。

  ②WeakMap的键名所指向的对象,不计入垃圾回收机制。

 

是不是你的耳朵是圆的,我的话是方的,所以你听不进去呀。
posted @ 2018-01-26 15:31  熊小可  阅读(136)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3