【ES6 笔记】Set集合与Map集合

Set 集合是一种无重复元素的列表,开发者们一般不会像访问数组元素那样逐一访问每个元素,通常的做法是检测给定的值在某个集合中是否存在。Map 集合内含多组键值对,集合中每个元素分别存放着可访问的键名和它对应的值,Map 集合经常被用于缓存频繁取用的数据。

ES6中的 Set 集合

Set 类型时一种有序列表,其中包含一些相互独立的非重复值,通过Set结合可以快速访问其中的数据,更可有效地追踪各种离散值。

  • 创建 Set 集合并添加元素
let set = new Set(); //创建Set集合
    set.add(5);
    set.add('5');
console.log(set.size); // 2
/*
* 在Set集合中,不会对所有值进行强制的类型转换,数字5和字符串“5”可以作为 
  两个独立的元素存在,
* 唯一列外的是,Set集合中的+0和-0被认为是相等的。
*/
let set = new Set(),
    key1 = {} ,
    key2 = {}; 
    set.add(key1);
    set.add(key2); 
console.log(set.size); //2
/*
* 由于key1和key2不会被转为字符串,他们是两个独立的地址引用,因而他们在Set集合中是两个独立的元素。
*/
let set = new Set();
    set.add(5);
    set.add('5');
    set.add(5);
console.log(set.size); //2

let constructorSet = new Set([1,2,3,4,5,5,5,5,5,5,5]);
console.log(constructorSet.size); //5
/*
* 由于第二次传入的数字5是一个重复值,因此不会被添加到集合中。
* Set集合会过滤掉重复的值从而保证集合中的元素各自唯一。
*/
  • 通过has()方法检测Set集合中是否存在某个值
let set = new Set();
set.add(5);
console.log(set.has(5)); //true
console.log(set.has(99)); // false
  • 移除元素
let set = new Set();

    set.add(6);
    set.add(5);

    console.log(set.has(5));  // true

    set.delete(5); //删除指定元素

    console.log(set.has(5)); //false
    console.log(set.size);  //1

    set.clear();  //清空set合集中的所有元素

    console.log(set.has(6));  //false
    console.log(set.size);  // 0
    
  • Set 集合中的forEach(callback, this)方法
    forEach()方法接受一下3个参数:
    1. value 当前值
    2. key 当前索引值
    3. 被遍历的Set集合本身
let set = new Set(['a','b']);

set.forEach((value,key,selfSet)=>{
      console.log(`Key is ${key} and value  is ${value}`);
      console.log(selfSet == set)
})
// Key is a and value  is a
// true
// Key is b and value  is b
// true

如果需要在回调中使用this引用,则可以将它作为第二个参数传入forEach()函数:

let set = new Set([1,2]);
let processor = {
    output(value){
        console.log(value)
    },
    process(dataSet){
        dataSet.forEach(function(value){
              this.output(value)
        },this)
    }
}
processor.process(set)
// 1
// 2
  • 将Set集合转换为数组
let set = new Set([1,2,3,4,5,5,5,5,5]);
let array = [...set];
console.log(array);  // [1,2,3,4,5]

以上过程自动移除了数组中的重复值,利用这个特性,可以创建并赋值一个无重复的数组:

function eliminateDuplicates(items){
      return [...new Set(items)];
}

let array = [1,1,1,1,2,2,3,4,5,5,5,5,5,5];
let noDuplicates = eliminateDuplicates(array);

console.log(noDuplicates);  // [1,2,3,4,5]

Weak Set 集合

Weak Set 集合只存储对象的弱引用,并且不可以存储原始值;集合中的弱引用如果是对象唯一的引用,则会被回收并释放相应内存。

  • 创建 Weak Set 集合
let weakSet = new WeakSet();  //创建Weak Set集合
let key = {};

weakSet.add(key);  //像Weak Set集合中添加对象

console.log(weakSet.has(key)); // true

weakSet.delete(key);  // 删除 Weak Set集合中的key引用

console.log(weakSet.has(key));  //false
let key1 = {};
let key2 = {};
let set = new WeakSet([key1, key2]);
console.log(set.has(key1));  // true
console.log(set.has(key2));  // true
/*
* 向WeakSet构造函数传入一个含有两个对象的数组,最后创建一个包含这两个对象的WeakSet集合
* WeakSet构造函数不接受任何原始值,如果数组中包含其他非对象值,会抛出错误
*/
  • 两种 Set 类型的主要区别
    两种Set类型之间最大的区别是Weak Set保存的是对象之的弱引用:
    1. 在WeakSet的实例中,如果向add()方法传入非对象参数会导致程序报错,而向has()和delete()方法传入非对象参数则会返回false
    2. Weak Set 集合不可迭代,所以不能被用于for-of循环
    3. Weak Set 集合不暴露任何迭代器,所以无法通过程序本身来检测其中的内容
    4. Weak Set 集合不支持forEach()方法
    5. Weak Set 集合不支持size属性

ES6中的 Map 集合

ES6中的 Map 类型时一种存储着许多键值对的有序列表,其中的键名和对应的值支持所有的数据类型。键名的等价性判断是通过调用Object.is()方法实现的。

  • 创建 Map 集合
let  map  = new Map();
map.set('name','欧阳不乖'); //接受两个参数:key 和 value
map.set('age',18);  

console.log( map.get('name') );  //'欧阳不乖'
console.log( map.get('age') );  //18
console.log( map.get('hobby') );  // undefined 集合中不存在的返回undefined
  • Map 集合支持的方法
    1. has(key) 检测指定的键名在Map集合中是否存在
    2. delete(key) 从Map集合中移除指定键名及其对应的值
    3. clear() 移除Map集合中所有的键值对
      Map 集合同样支持size属性,表示当前集合中包含的键值对的数量
let map = new Map();
map.set('name','欧阳不乖');
map.set('age',18);

console.log(map.size);  //2

console.log(map.has('name'));  // true
console.log(map.get('name'));  // 欧阳不乖

console.log(map.has('age'));  // true
console.log(map.get('age'));  // 18

map.delete('name');  // 删除name键
console.log(map.has('name'));  // false
console.log(map.get('name'));  // undefined
console.log(map.size);  // 1

map.clear();  //清空所有的集合
console.log(map.has('age'));  // false
console.log(map.get('age'));  // undefined
console.log(map.size);  // 0
  • Map 集合的初始化方法
    可以向 Map 构造函数传入数组来初始化一个 Map 集合
let map = new Map([['name', '欧阳不乖'],['age', 18]]);
console.log( map.has('name') );  // true
console.log(map.get('name'));  // 欧阳不乖
console.log(map.size);  //2
  • Map 集合的forEach()方法
    forEach()方法接受一下3个参数:
    1. value 当前值
    2. key 当前索引值
    3. 被遍历的Map集合本身
let map = new Map([['name', '欧阳不乖'],['age', 18]]);
map.forEach((value, key, selfMap)=>{
      console.log(`Key is ${key} and value is ${value}`);
      console.log(selfMap==map )
})
// Key is name and value is 欧阳不乖
// true
// Key is age and value is 18
// true

Map 集合和 Set 集合很类似,充分理解其中一个,另一个自然就明白了。

Weak Map 集合

Weak Map 是弱引 Map 集合,也可用于存储对象的弱引用。Weak Map集合中的键名必须是一个对象,如果使用field对象键名会报错;集合中保存的是这些对象的弱引用,如果弱引用之外不存在其他的强引用,引擎的垃圾回收机制会自动回收这个对象,同时也会移除Weak Map集合中的键值对。

  • 使用Weak Map集合
let map = new WeakMap();
let key = {};
map.set( key, 'Here Is Object Desc');

console.log(map.get(key)); //  Here Is Object Desc

// 移除key元素
key = null;
// 此时WeakMap集合为空
  • Weak Map集合的初始化方法
    调用 WeakMap构造函数并传入一个数组容器,容器内包含其他数组,每一个数组由两个元素构成:第一个元素是一个键名,传入的值必须是非null的对象;第二个元素是这个键对应的值,可以是任意类型:
let key1 = {};
let key2 = {};
let map = new WeakMap( [ [key1, 'Hello'], [key2, 'World'] ] );

console.log(map.has(key1));  // true
console.log(map.get(key1));   // Hello
console.log(map.size ); // undefined

Weak Map 不支持size属性

  • Weak Map集合支持的方法
    1. has(key) 检测指定的键名在Weak Map集合中是否存在
    2. delete(key) 从Weak Map集合中移除指定键名及其对应的值
let map = new WeakMap();
let key1 = {};
let key2 = {};
map.set(key1,'欧阳不乖');
map.set(key2,18);

console.log(map.has(key1));  // true
console.log(map.get(key1));  // '欧阳不乖'

map.delete(key1)
console.log(map.has(key1));  // false
console.log(map.get(key1));  // undefined
  • Weak Map集合的使用方法及使用限制
    当要在Weak Map 和Map集合之间做出选择时,需要考虑的主要问题是,是否只用对象作为集合的键名,如果是,那么Weak Map集合是最好的选择。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 207,248评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,681评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,443评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,475评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,458评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,185评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,451评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,112评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,609评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,083评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,163评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,803评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,357评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,357评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,590评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,636评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,925评论 2 344

推荐阅读更多精彩内容