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. 搭建JSP开发环境

    所谓"工欲善其事,必先利其器",要进行JSP网站开发,首先需要把整个开发环境搭建好. JSP开发运行环境 -开发工具包JDK(Java Develop Kit),即Java开发工具 ...

  2. 201521123035《Java程序设计》第四周学习总结

    本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. 本周还讲了注释与类设计.老师用例子向我们展示实际生活中一个类里面包含了哪些属性,并由此联想到如果自 ...

  3. 201521123026 《Java程序设计》第三周学习总结

    1. 本章学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识组织起来.请使用纸笔或者下面的工具画出本周学习到的知识点.截图或者拍照上传. 2. 书面作 ...

  4. 201521123070 《JAVA程序设计》第3周学习总结

    1. 本章学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识组织起来.请使用纸笔或者下面的工具画出本周学习到的知识点.截图或者拍照上传. http:/ ...

  5. 201521123080《Java程序设计》第1周学习总结

    #1. 本周学习总结 Java开发环境,如何用记事本和eclipse进行编程. #2. 书面作业 Q1.为什么java程序可以跨平台运行?执行java程序的步骤是什么?(请用自己的语言书写)      ...

  6. PTA分享码-Java

    主要用于Java语法练习,非竞赛类题目.   1. Java入门          959dbf0b7729daa61d379ec95fb8ddb0   2. Java基本语法   23bd8870e ...

  7. Eclipse rap 富客户端开发总结(4):如何搭建 rap 中文开发环境

    Rap中文开发环境搭建大约分为2个部分 1.  rap国际化,详细参加文章(rap开发经验总结(5)-rap国际化之路) 2.rap自带的JFace ,Dialog 等国际化 1.中文包下载地址: h ...

  8. Struts2第十三篇【防止表单重复提交】

    回顾防止表单重复提交 当我们学习Session的时候已经通过Session来编写了一个防止表单重复提交的小程序了,我们来回顾一下我们当时是怎么做的: 在Servlet上生成独一无二的token,保存在 ...

  9. MyEclipse 快捷键问题

    解决Myeclipse提示快捷键Alt+/不可用问题 http://blog.163.com/cd-key666/blog/static/648929422011229123826/ 解决Myecli ...

  10. JSP页面格式化数字或时间 基于jstl的

    jsp页面格式化数字或时间 转载自: http://blog.csdn.net/hakunamatata2008/archive/2011/01/21/6156203.aspx Tags fmt:re ...