Set

Set 对象允许你存储任何类型的 唯一值, 无论是 原始值(一共6种,string, number, boolean, undefined, null,和 es6 新增的 symbol) 还是 对象引用(Object)。

先用代码体会下这段概念的含义,直接在 Chrome 控制台创建一个 Set 数据类型,并因此向 Set 的实例中添加 原始值 和 对象引用,查看最终的 Set 数据机构和成员个数

上图中,我们依次在 Set 数据结构中存储了5种常见的原始数据类型和2种Object数据类型,最终全部存储成功,并且查看到有7个成员

1、语法:

new Set([iterable]);

参数:iterable

可以传入一个 可迭代对象 用来初始化 Set 数据类型,它的所有元素将被添加到新的 Set 中。如果不指定此参数或者其值为 null,则新的Set 为空。

(可迭代对象包括:Array, String, Set, Map, TypedArray, 函数的 arguments 对象,NodeList 对象等)

返回值:

一个新的 Set 对象

我们现在依次在 Chrome 控制台中用 可迭代对象 和 普通原始数据类型(String 属于可迭代对象)来初始化 Set 数据类型

再来看一个 NodeList 作为参数来初始化 Set 数据类型的小栗子:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div>11</div>
<div>22</div>
<div>33</div>
<script>
var divs = document.querySelectorAll('div');
var set_NodeList = new Set(divs);
console.log(set_NodeList);
</script>
</body>
</html>

输出结果:

2、概括:

(1)、Set 中的元素是唯一的

let arr=[1,2,3,1,'2'];
let list2=new Set(arr); console.log('unique',list2); // Set(4) {1, 2, 3, "2"}

(2)、向 Set 加入值的时候,不会发生类型转换,所以 5 和 "5" 是两个不同的值

let s6 = new Set();
s6.add(5);
s6.add(6);
s6.add('5');
s6.add(6);
console.log(s6); // Set(3) {5, 6, "5"}

(3)、NaN, undefined 和 null 都可以被存储在 Set 中,在 Set 内部, 两个 NaN 是相等的(尽管在 es5 中 NaN != NaN)

(4)、两个对象总是不相等的(包括空对象)

let s8 = new Set();
s8.add({});
s8.add({});
console.log(s8); // Set(2) {Object {}, Object {}} s8.add({'name': 'roger'});
s8.add({'age': 27});
console.log(s8); // Set(4) {Object {}, Object {}, Object {name: "roger"}, Object {age: 27}}

(5)、数组去重   [ ...new Set( array ) ]

let arr1 = ['apple', 'huawei', 'mi', 'oppo', 'apple'];
let arr2 = [...new Set(arr1)];
console.log(arr2); // ["apple", "huawei", "mi", "oppo"]

(6)、Array.from 方法可将 Set 结构转为数组

let s9 = new Set();
s9.add([1,2,3]);
let arr = Array.from(s9);
console.log(Array.isArray(arr)); // true // 这就提供了去除数组重复成员的另一种方法
function dedupe(array) {
return Array.from(new Set(array));
}
dedupe([1, 1, 2, 3]); // [1, 2, 3]

3、遍历操作

Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)

(1)、四个操作方法

add (value):添加某个值,返回 Set 结构本身

delete(value):删除某个值,返回一个 bool 值,表示是否删除成功

clear(value):清除所有成员,没有返回值

has(value):返回一个 bool 值,表示该值是否是 Set 的成员

另外,size 相当于数组的 length 属性,表示 Set 成员的个数

let list = new Set ();
list.add(5);
list.add(7);
console.log('size',list.size); // size 2 // 数组作为参数
let arr = [1,2,3,4,5];
let list1 = new Set (arr);
console.log('size',list1.size); // size 5 // 数组去重
let list2 = new Set();
list2.add(2);
list2.add(3);
list2.add(3);
console.log('list2',list2); // Set(2) {2, 3} let arr3=[1,2,3,1,'2'];
let list3=new Set(arr3);
console.log('unique',list3); // Set(4) {1, 2, 3, "2"}
let arr4 = ['add', 'delete', 'has', 'clear'];
let list4 = new Set (arr4); console.log('has', list4.has('add')); // has true console.log('delete', list4.delete('add'), list4); // delete true Set(3) {"delete", "has", "clear"} console.log('clear', list4.clear(), list4); // clear undefined Set(0) {}

(2)、四个遍历方法

keys():返回键名

values():返回键值

entries():返回键值对

forEach():使用回调函数遍历每个成员

let arr7 = ['one', 'two', 'three', 'four', 'five'];
let list7 = new Set(arr7); for (let key of list7.keys()){
console.log('keys',key);
} // keys one
// keys two
// keys three
// keys four
// keys five for(let value of list7.values()){
console.log('values',value);
} // values one
// values two
// values three
// values four
// values five for(let entries of list7.entries()){
console.log('entries', entries)
} entries (2) ["one", "one"]
entries (2) ["two", "two"]
entries (2) ["three", "three"]
entries (2) ["four", "four"]
entries (2) ["five", "five"] list7.forEach(function(item){
console.log(item)
}) // one
// two
// three
// four
// five

WeakSet

WeakSet 对象 与 Set 类似,也是不重复的值的集合

它与 Set 对象的区别有两点:

• WeakSet 的成员 只能是对象,不能是其它类型的值。而 Set 对象都可以;并且,WeakSet 没有 size 属性

• WeakSet 中的对象都是弱引用,如果没有其它变量或属性引用这个对象值,那么这个对象值会被当垃圾回收掉。正因如此,WeakSet 对象是无法遍历的,没有办法拿到它所包含的元素

1、语法:

new WeakSet([iterable]);

参数:iterable

如果传入一个 可迭代对象, 则该对象所有的 迭代值 都会被自动添加进生成的 WeakSet 对象中

注意:初始化 WeakSet 的参数是有2个要求的

(1)、传入的参数必须是一个 可迭代对象

(2)、可迭代对象的值必须是 迭代值

通过一个例子来理解这段话:

2、方法

WeakSet.prototype.add(value):向 WeakSet 实例添加一个新成员。
WeakSet.prototype.delete(value):清除 WeakSet 实例的指定成员。
WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在 WeakSet 实例之中。

Map

Map 对象保存键值对。任何值(包括原始值和对象)都可以作为一个键或值

1、语法

new Map([iterable])

参数:iterable

与 WeakSet 类似,初始化Map时,Map 的参数必须是 iterable 对象,该对象的值也必须为 iterable值

JavaScript 的对象,本质是键值对的集合(Hash 结构),但是传统上只能用字符串当键,这给它的使用带来了很大的限制。

例如,在《JavaScript高级程序设计》一书中,关于 Object 类型的介绍中,有这么一段话 “ 如果属性名中包含会导致语法错误的字符,或者属性名使用的是关键字或保留字,也可以使用方括号表示法。例如:”

person["first name"] = "Nicholas"; 

“ 由于 ‘first name’ 中包含一个空格,所以不能用点表示法来访问它。然而,属性名中是可以包含非字母非数字的,这时候就可以使用方括号表示法来访问它们。 ”

现在有一个如下结构的对象,该如何给这样一个对象添加和读取新成员呢?

{
map:contra : {description: 'Asynchronous flow control'},
     map:dragula: {description: 'Drag and drop'},
     map:woofmark: {description: 'Markdown and WYSIWYG editor'} }

我们可以按照如下方法来实现:

   var obj = {}
// 给对象添加成员
function add(name, meta){
obj['map:'+name] = meta
}
// 读取对象成员
function get(name){
return obj['map:'+name]
} add('contra', { description: 'Asynchronous flow control' })
add('dragula', { description: 'Drag and drop' })
add('woofmark', { description: 'Markdown and WYSIWYG editor' }) get('contra')

但如果使用 Map 结构来实现的话,就可以简单很多

    var map = new Map()
map.set('contra', { description: 'Asynchronous flow control' })
map.set('dragula', { description: 'Drag and drop' })
map.set('woofmark', { description: 'Markdown and WYSIWYG editor' })
console.log(map)

结果如下:

通过前面的例子,我们来进一步了解下Map 和 Object 之间的相似点和不同点

相似点:

• 都是键值对的集合(Hash 结构)

• 允许按键 添加、删除一个值

• 可以删除键

• 可以检测一个键是否绑定了值

不同点:

• Object 的键只能是 字符串 或 Symbol,Map 的键可以是任意值

• 可以通过 size 属性获取 Map 的键值对个数,而 Object 的键值对个数只能手动确认

• Object 都有自己的原型 prototype,不过,从 ES5 开始,可以通过 “ map = Object.create( null ) ” 来创建一个没有原型的对象

2、Map 实例的属性和方法

(1)、set(key, value)

set 方法设置键名 key 对应的键值 value,然后返回整个 Map 结构。如果 key 已经有值,则键值会被更新,否则就新生成该键

    const m = new Map();

    m.set('edition', 6)        // 键是字符串       Map(1) {"edition" => 6}
m.set(262, 'standard') // 键是数值 Map(2) {"edition" => 6, 262 => "standard"}
m.set(undefined, 'nah') // 键是 undefined Map(3) {"edition" => 6, 262 => "standard", undefined => "nah"} m.set(['123'], 456) // 键是数组 Map(4) {"edition" => 6, 262 => "standard", undefined => "nah", ["123"] => 456}
 

set 方法返回的是当前的 Map 对象,因此可以采用链式写法

let map = new Map()
.set(1, 'a')
.set(2, 'b')
.set(3, 'c');
// Map(3) {1 => "a", 2 => "b", 3 => "c"}

(2)、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!
m.get('world') // undefined

(3)、size 属性

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

    const map = new Map()
map.set('foo', true)
map.set('bar', false) console.log(map.size) //

(4)、has(key)

has 方法返回一个 bool 值,表示某个键是否在当前的 Map 对象中

const m = new Map();

m.set('edition', 6);
m.set(262, 'standard');
m.set(undefined, 'nah'); m.has('edition') // true
m.has('years') // false
m.has(262) // true
m.has(undefined) // true

(5)、delete(key)

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

const m = new Map();
m.set(undefined, 'nah');
m.has(undefined) // true m.delete(undefined)
m.has(undefined) // false

(6)、clear()

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

let map = new Map();
map.set('foo', true);
map.set('bar', false); map.size //
map.clear()
map.size //

3、遍历方法

keys():返回键名的遍历器

values():返回键值的遍历器

entries():返回所有成员的遍历器

forEach():返回Map的所有成员

也可以使用 forEach() 方法遍历

var myMap = new Map();
myMap.set(0, 'Zero');
myMap.set(1, 'One'); myMap.forEach(function(value, key){
console.log(key+'='+value)
}, myMap) // 0=Zero
// 1=One

4、与其它数据结构的互相转换

(1)、Map 转为数组,使用扩展运算符(...)

var map = new Map();
map.set({'hello': 'world'})
.set([1, NaN, 'china']); var map_array = [...map];
console.log(map_array); // [[{hello: "world"}, undefined], [[1, NaN, "china"], undefined]

(2)、数组转为Map,将数组传入Map构造函数

var map = new Map([['hello', null],['world', undefined]]);

// Map(2) {"hello" => null, "world" => undefined}

WeakMap

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

1、语法

new WeakMap([iterable])

参数:iterable

iterable 是一个2元数组或者可遍历的且其元素是键值对的对象

var mp = new WeakMap();
mp.set({'age': 27}, 2017); // WeakMap {{age: 27} => 2017} mp.set(1,2); // Uncaught TypeError: Invalid value used as weak map key

2、注意点:

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

(2)、WeakMap的键名所指向的对象,不计入垃圾回收机制

(3)、WeakMap 没有遍历操作,无法清空,也没有 size 属性

3、方法

WeakMap只有四个方法可用:get()、set()、has()、delete()

var wm1 = new WeakMap(),
wm2 = new WeakMap(),
wm3 = new WeakMap();
var o1 = {},
o2 = function(){},
o3 = window; wm1.set(o1, 37);
wm1.set(o2, "azerty");
wm2.set(o1, o2); // value可以是任意值,包括一个对象
wm2.set(o3, undefined);
wm2.set(wm1, wm2); // 键和值可以是任意对象,甚至另外一个WeakMap对象
wm1.get(o2); // "azerty"
wm2.get(o2); // undefined,wm2中没有o2这个键
wm2.get(o3); // undefined,值就是undefined wm1.has(o2); // true
wm2.has(o2); // false
wm2.has(o3); // true (即使值是undefined) wm3.set(o1, 37);
wm3.get(o1); //
wm3.clear();
wm3.get(o1); // undefined,wm3已被清空
wm1.has(o1); // true
wm1.delete(o1);
wm1.has(o1); // false

Set 和 Map 数据结构的更多相关文章

  1. 11 Set和Map数据结构

    Set和Map数据结构 Set WeakSet Map WeakMap 首先 这四个对象都是 数据结构. 用于存放数据 Set 类似数组. 但是不能重复. 如果你有重复数据,会自动忽略 属性 size ...

  2. ES6 之 Set数据结构和Map数据结构 Iterator和for...of循环

    ECMAScript 6 入门 Set数据结构 基本用法 ES6提供了新的数据结构Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set本身是一个构造函数,用来生成Set数据结构. va ...

  3. ES6中的Set、Map数据结构

    Map.Set都是ES6新的数据结构,他们都是新的内置构造函数.也就是说typeof的结果,多了两个. 他们是什么:  Set是不能重复的数组.    Map是可以任何东西当做键的对象: ES6 提供 ...

  4. ECMAScript 6之Set和Map数据结构

    Set 基本用法 ES6提供了新的数据结构Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set本身是一个构造函数,用来生成Set数据结构. var s = new Set(); [2, ...

  5. set和 map 数据结构

    set/map数据结构 创建: var  s=new Set(); 添加成员 s.add(1) 遍历 for of s.froEach 删除 s.delete() 判断存在 s.has() 清除 s. ...

  6. es6学习笔记-set和map数据结构

    ES6 提供了新的数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set 本身是一个构造函数,用来生成 Set 数据结构. const s = new Set(); [2, 3 ...

  7. js-ES6学习笔记-Set和Map数据结构

    1.ES6 提供了新的数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set 本身是一个构造函数,用来生成 Set 数据结构. 2.Set 函数可以接受一个数组(或类似数组的对 ...

  8. JavaScript(ES6)学习笔记-Set和Map数据结构(一)

    一.Set 1.ES6 提供了新的数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set 本身是一个构造函数,用来生成 Set 数据结构. , , , , ']); s; // ...

  9. Map 数据结构

    JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键.这给它的使用带来了很大的限制. 为了解决这个问题,ES6 提供了 Map 数据结构. ...

  10. go map数据结构

    map数据结构 key-value的数据结构,又叫字典或关联数组 声明: var map1 map[keytype]valuetype var a map[string]string var a ma ...

随机推荐

  1. JavaSE(十)集合之Set

    今天这一篇把之前没有搞懂的TreeSet中的比较搞得非常的清楚,也懂得了它的底层实现.希望博友提意见! 一.Set接口 1.1.Set集合概述 Set集合:它类似于一个罐子,程序可以依次把多个对象 “ ...

  2. Squid代理服务器安装

    代理服务器的功能是代替网络用户去访问网络信息,并把获得的信息返回给用户,其工作步骤大致如下: ) 客户机向代理服务器发起访问互联网的请求 ) 代理服务器收到请求后检查请求是否被允许,如果允许将会进行下 ...

  3. 201521123065《java程序设计》第8周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 1.2 选做:收集你认为有用的代码片段 1.Map通过get(key)来获取值: 2.HashMap和Hash ...

  4. 201521123113《Java程序设计》第6周学习总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 1.2 可选:使用常规方法总结其他上课内容. 使用NetB ...

  5. 201521145048《Java程序设计》第12周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对象(属性:int id, String name,int age,doubl ...

  6. 201521123033《Java程序设计》第13周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu ...

  7. 201521123116 《java程序设计》第十周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 Q1 finally 题目4-2 1.1 截图你的提交结果(出现学号) 1.2 4-2中fi ...

  8. JAVA课程设计——团队(&个人)博客

    JAVA课程设计--团队(&个人)博客 1. 团队名称.团队成员介绍(需要有照片) 团队名称:是独立小分队啦 团队成员介绍:包梦榕 网络1513 201521123068 2. 项目git地址 ...

  9. Java课程设计-计算器 郑子杰(201521123021)

    1.团队课程设计博客链接 http://www.cnblogs.com/I-love-java/p/7058752.html 2.个人负责模块或任务说明 ①图形界面的初始化 ②图形界面的排版设计 ③主 ...

  10. 参加IMWebConf 2017 前端开发者大会是什么体验?

    周六作为特邀讲师之一参加了IMWebConf 2017 前端开发者大会的主题演讲,主题为<WebAssembly:面向未来的web开发技术>.本次大会质量非常高,来自国内外的技术专家带了很 ...