前言

当我们需要存储一些数据的时候,首先想到的是定义一个变量用来存储,之后我们可能学了数组,发现数组比变量可以存储更多的数据,接着可能有其它的存储数据的方法等等,然而我今天需要介绍的是在ES6中比较常见使用的数据类型结构,Set和Map。

Set数据结构

一、Set简介

  • set中成员的值都是唯一的,没有重复的值

  • 向set中添加成员时,不会发生类型转换

  • 向set中添加的对象总是不想等

二、常用的属性和方法

属性:

  • size:返回set实例的成员总数

方法:

  • add():添加某个值,返回set本身

  • delete():删除某个值,返回一个布尔值,判断删除是否成功

  • has():返回一个布尔值,表示该值是否为set成员

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

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

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

  • entries():返回键值对的遍历器

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

三、实例剖析

为了方便大家更好的了解和学习set,我在这里会将这些方法和属性进行分类整理和讲解

1、set的基本用法

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>数组去重</title>
</head>
<body>
<script type="text/javascript">
const set=new Set(); //创建set数据结构
[1,1,2,3,4,5].forEach(x=>{
set.add(x);
})
console.log(set); //1,2,3,4,5
for(let i of set){
console.log(i);
}
</script>
</body>
</html>

可以看到向Set添加成员时,不会添加重复的值

2、数组作为参数传入到set结构中

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<script type="text/javascript">
// const set=new Set([1,2,3]);
// console.log(...set);//1,2,3,使用扩展运算符 const set=new Set(document.querySelectorAll('div'));
console.log(set.size);//5 size返回set实例的成员总数
//如上代码相当于
const item=new Set();
document.querySelectorAll('div').forEach(x=>{
item.add(x);
})
console.log(item);
console.log(item.size);//5
</script>
</body>
</html>

3、set中添加的值不会发生类型转换

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>向set中添加成员时,不会发生类型转换</title>
</head>
<body>
<script type="text/javascript">
let mySet=new Set();
mySet.add(5);
mySet.add('5');
console.log(mySet);//5,'5'
let set=new Set();
let a=NaN;
let b=NaN;
set.add(a);
set.add(b);
console.log(set);//NaN
</script>
</body>
</html>

向 Set 加入值的时候,不会发生类型转换,所以5"5"是两个不同的值。Set 内部判断两个值是否不同,使用的算法叫做“Same-value-zero equality”,它类似于精确相等运算符(===),主要的区别是向 Set 加入值时认为NaN等于自身,而精确相等运算符认为NaN不等于自身。

4、set中添加的对象总是不想等的

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>向set中添加的对象总是不想等</title>
</head>
<body>
<script type="text/javascript">
let set=new Set();
set.add({});//向set中添加一个空对象
console.log(set.size);//1
set.add({});//向set中添加另一个空对象
console.log(set.size);//2
</script>
</body>
</html>

由于两个空对象不相等,所以它们被视为两个值

5、Array.from()方法

Array.from()可以将set结构转为数组,这就提供了去除数组重复成员的另一种方法

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Array.from()方法</title>
</head>
<body>
<script type="text/javascript">
const items=new Set([1,2,3,4,5]);
console.log(items);//1,2,3,4,5
const array=Array.from(items);
console.log(array);//1.2.3,4,5
//Array.from()方法实现数组去重
function dedupe(arr){
return Array.from(new Set(arr))
}
console.log(dedupe([1,1,2,3]));//1,2,3
</script>
</body>
</html>

四.遍历的应用

1、数组去重

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>数组去重</title>
</head>
<body>
<script type="text/javascript">
let set=new Set(['red','blue','green']);
let arr=[...set];
console.log(arr);//red,blue,green
//数组去重
let arrs=[1,1,3,3,4,5,6];
let unique=[...new Set(arrs)];
console.log(unique);//1,3,4,5,6
</script>
</body>
</html>

2、间接使用数组的方法

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>间接使用数组的方法</title>
</head>
<body>
<script type="text/javascript">
let set=new Set([1,2,3,4,5]);
set=new Set([...set].map(x=>x*2));//使用数组的map方法
console.log(set);//2,4,6,8,10
let mySet=new Set([1,2,3,4,5]);
mySet=new Set([...mySet].filter(x=>x%2==0));//使用数组的filter方法
console.log(mySet);//2,4
</script>
</body>
</html>

3、实现并集,交集,差集

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>实现并集,交集,差集</title>
</head>
<body>
<script type="text/javascript">
let a=new Set([1,2,3]);
let b=new Set([4,3,2]);
//并集
let union=new Set([...a, ...b]);
console.log(union);//1,2,3,4
//交集
let intersect=new Set([...a].filter(x=>b.has(x)));
console.log(intersect);//2,3
//差集
let difference=new Set([...a].filter(x=>!b.has(x)));
console.log(difference);//1
</script>
</body>
</html>

4、同步改变原来的 Set 结构

如果想在遍历操作中,同步改变原来的 Set 结构,目前没有直接的方法,但有两种变通方法。一种是利用原 Set 结构映射出一个新的结构,然后赋值给原来的 Set 结构;另一种是利用Array.from方法。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>同步改变原来的 Set 结构</title>
</head>
<body>
<script type="text/javascript">
//方法一
let set=new Set([1,2,3]);
set=new Set([...set].map(val=>val*2));
console.log(set);//2,4,6
//方法二
let mySet=new Set([1,2,3]);
mySet=new Set(Array.from(mySet,val=>val*2));
console.log(mySet);//2,4,6
</script>
</body>
</html>

五、set实例属性和方法

1、size属性

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>set中的size属性</title>
</head>
<body>
<script type="text/javascript">
const set=new Set();
//向set中添加成员
set.add(1);
set.add(2);
set.add(3);
//链式方法
set.add(4).add(5).add(6);
console.log(set.size);//6
</script>
</body>
</html>

2、操作方法add()、delete()、has()、clear()

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>set中的操作方法add()、delete()、has()、clear()</title>
</head>
<body>
<script type="text/javascript">
const set=new Set();
//向set中添加成员
set.add(1);
set.add(2);
set.add(3);
//链式方法
set.add(4).add(5).add(6);
console.log(set.size);//6
console.log(set.has(1));//true
set.delete(1);
console.log(set.has(1));//false
set.clear();//清空全部set成员
console.log(set.size);//0
</script>
</body>
</html>

3、遍历方法keys()、values()、entries()、forEach()

注意:set的遍历顺序就是插入顺序,由于set没有键名,只有键值(或者说键名和键值是同一个值),所以keys()和values()方法的行为完全一致

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>set中的遍历方法keys(),values(),entries(),forEach()</title>
</head>
<body>
<script type="text/javascript">
let set=new Set(['red','blue','green']);
//遍历全部的key
for(let key of set.keys()){
console.log(key);//red,blue,green
}
//遍历全部的value
for(let value of set.values()){
console.log(value);//red,blue,green
}
//遍历全部的key和value
for(let item of set.entries()){
console.log(item);//['red','red'],['blue','blue'],['green','green']
}
set.forEach((key,value)=>{
console.log(key+':'+value);
})
</script>
</body>
</html>

Map数据结构

一、Map简介

es6中的map很大程度上和set相似,但是map是以键值对的形式存储数据的

二、常用的属性和方法

属性:

  • size:返回map结构的成员总数

方法:

  • set(key,value):设置键名key对应的键值value,然后返回整个map结构,如果key已经有值,则键值会被更新,否则就新生成该键

  • get(key):读取key对应的键值,如果找不到key,则返回undefined

  • has(key):返回一个布尔值,表示某个键是否在当前map对象中

  • delete(key):删除某个key,返回true,如果删除失败,返回false

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

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

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

  • entries():返回键值对的遍历器

  • forEach():遍历map的所有成员

三、实例剖析

1、size属性

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>map中的size属性</title>
</head>
<body>
<script type="text/javascript">
const map=new Map();
map.set('foo',true);
map.set('bar',false);
console.log(map.size);//2
</script>
</body>
</html>

2、set(key,value)方法

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>map中的set()方法</title>
</head>
<body>
<script type="text/javascript">
const map=new Map();
map.set('1','a');//键是字符串
map.set(2,'b');//键是数值
map.set(undefined,'3');//键是undefined
console.log(map);//'1'=>a,2=>b,undefinde=3
const myMap=new Map();
//链式写法
myMap.set(1,'a').set(2,'b').set(3,'c');
console.log(myMap);//1=>a,2=>b,3=>c
</script>
</body>
</html>

3、get(key)方法

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>map中的get()方法</title>
</head>
<body>
<script type="text/javascript">
const map=new Map();
const hello=function(){
console.log('你好');
}
map.set(hello,'es6');//键是函数
console.log(map.get(hello));//es6
</script>
</body>
</html>

4、has(key)方法

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>map中的has()方法</title>
</head>
<body>
<script type="text/javascript">
const map=new Map();
//链式写法
map.set('a',1).set('b',2).set('c',3);//向map中添加成员
console.log(map.has('a'));//true
console.log(map.has('b'));//true
console.log(map.has('c'));//true
console.log(map.has('d'));//false
</script>
</body>
</html>

5、delete(key)方法

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>map中的delete方法</title>
</head>
<body>
<script type="text/javascript">
const map=new Map();
map.set('a',1);
console.log(map.has('a'));//true
map.delete('a');//删除键a
console.log(map.has('a'));//false
</script>
</body>
</html>

6、clear()方法

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>map中的clear()方法</title>
</head>
<body>
<script type="text/javascript">
const map=new Map();
map.set('foo',true);//向map中添加成员
map.set('bar',false);
console.log(map.size);//2
map.clear();//清除map中的全部成员
console.log(map.size);//0
</script>
</body>
</html>

7、遍历方法keys()、values()、entries()、forEach()

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>遍历方法keys(),values(),entries(),forEach()</title>
</head>
<body>
<script type="text/javascript">
const map=new Map();
//向map中添加成员
map.set(1,'a');
map.set(2,'b');
map.set(3,'c');
//遍历全部的键
for(let key of map.keys()){
console.log(key);//1,2,3
}
//遍历全部的值
for(let values of map.values()){
console.log(values);//a,b,c
}
//遍历全部的键和值
for(let [key,value] of map.entries()){
console.log(key,value);//1=>a,2=>b,3=>c
}
for(let item of map.entries()){
console.log(item[0],item[1]);//1=>a,2=>b,3=>c
}
for(let [key,value] of map){
console.log(key,value);//1=>a,2=>b,3=>c
}
map.forEach(function(value,key){
console.log(key,value);
})
</script>
</body>
</html>

注意:

这里的forEach()是值在前,键在后

8、map结构转为数组

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>map结构转为数组</title>
</head>
<body>
<script type="text/javascript">
const map=new Map([
[1,'one'],
[2,'two'],
[3,'three']
]);
console.log([...map.keys()]);//[1,2,3]
console.log([...map.values()]);//one,two,three
console.log([...map]);//[1,one],[2,two],[3,three]
console.log([...map.entries()]);//[1,one],[2,two],[3,three]
const map1=new Map(
[...map].filter(([key,value])=>key<3)//使用数组的filter方法
);
console.log(map1);//1=>one,2=>two
</script>
</body>
</html>

三、Map与其它数据结构的转换

作为键值对存储数据的map与其它数据也可以进行转换,我们看下下面的案例

1、Map转为数组

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

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Map转为数组</title>
</head>
<body>
<script type="text/javascript">
const map=new Map();//创建map数据结构
map.set(true,);//向map中添加成员
map.set({foo:},['abc']);
console.log([...map]);//[[true,7],[{foo:3},['abc']]];
</script>
</body>
</html>

2、数组转为Map

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

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>数组转为map</title>
</head>
<body>
<script type="text/javascript">
const map=new Map([
[true,7],
[{foo:3},['abc']]
]);
console.log(map);
//map{
//true=>7,
//object:{foo:3}=>['abc'];
//}
</script>
</body>
</html>

3、Map转为对象

如果所有map的键都是字符串,它可以无损的转为对象,如果有非字符串的键名,那么这个键名会被转为字符串,再作为对象的键名

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>map转为对象</title>
</head>
<body>
<script type="text/javascript">
function strMapObj(strMap){
let obj=Object.create(null);//创建一个新对象
for(let [key,value] of strMap){//遍历循环strMap
obj[key]=value;
}
return obj;
}
const map=new Map().set('yes',true).set('no',false);
console.log(strMapObj(map));//{yes:true,no:false}
</script>
</body>
</html>

在这里了我需要讲解一下Object.create()这个方法,官方的意思是:Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试Object.create()方法</title>
</head>
<body>
<script type="text/javascript">
const person={
isHuman: false,
printIntroduction: function () {
console.log(this.name,this.isHuman);
}
}
const me = Object.create(person);
me.name = "Matthew";
me.isHuman = true;
me.printIntroduction();//Mattew,true
</script>
</body>
</html>

4、对象转为Map

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>对象转为map</title>
</head>
<body>
<script type="text/javascript">
function objToMap(obj){
let map=new Map();
for(let key of Object.keys(obj)){
map.set(key,obj[key]);
}
return map;
}
console.log(objToMap({yes:true,no:false}));//yes=>true,no=>false
</script>
</body>
</html>

在这里讲解Object.keys()方法,官方解释:Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用,for..in循环遍历该对象时返回的顺序一致 。如果对象的键-值都不可枚举,那么将返回由键组成的数组。

参数:

要返回其枚举自身属性的对象

返回值:

一个表示给定对象的所有可枚举属性的字符串数组

// simple array
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2'] // array like object
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2'] // array like object with random key ordering
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // console: ['2', '7', '100'] // getFoo is a property which isn't enumerable
var myObj = Object.create({}, {
getFoo: {
value: function () { return this.foo; }
}
});
myObj.foo = 1;
console.log(Object.keys(myObj)); // console: ['foo']

5、Map转为JSON字符串

map转为json要区分两种情况,一种情况时map的键名都是字符串,这时可以选择转为对象json,另一种情况是map的键名有非字符串,这时可以选择转为数组json。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>map转为json</title>
</head>
<body>
<script type="text/javascript">
function strMapToObj(strMap){
let obj=Object.create(null);//创建一个新对象
for(let [key,value] of strMap){
obj[key]=value;
}
return obj;
}
function strMapToJson(strMap){
return JSON.stringify(strMapToObj(strMap));
}
let map=new Map().set('yes',true).set('no',false);
let obj=strMapToJson(map);
console.log(obj);//{'yes':true,'no':false}
function mapToArrayJson(map){
return JSON.stringify([...map]);
}
let fooMap=new Map().set(true,7).set({foo:3},['abc']);
let foo=mapToArrayJson(fooMap);
console.log(foo);//[[true:7],[{foo:3},['abc']]]
</script>
</body>
</html>

6、JSON字符串转为Map

json转为map,正常情况下所有键名都是字符串,但是有一种特殊情况,整个json就是一个数组,且每个数组成员本身,又是一个有两个成员的数组,这时它可以一一对应的转为map,这往往是map转为数组json的逆操作。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>json转为map</title>
</head>
<body>
<script type="text/javascript">
function objTostrMap(obj){
let map=new Map();
for(let key of Object.keys(obj)){
map.set(key,obj[key]);
}
return map;
}
function jsonToStrMap(jsonStr){
return objTostrMap(JSON.parse(jsonStr));
}
let obj1=jsonToStrMap('{"yes": true, "no": false}')
console.log(obj1);//yes=>true,no=>false
function jsonToMap(jsonStr){
return new Map(JSON.parse(jsonStr));
}
let obj2=jsonToMap('[[true,7],[{"foo":3},["abc"]]]')//true=>7,{foo:3}=>['abc']
console.log(obj2);
</script>
</body>
</html>

本文参考:

http://es6.ruanyifeng.com/#docs/set-map

总结

本章我们主要学习了ES6中set和map相关的属性和方法,set和map的方法中有很多都是相同的方法,has()、delete()、clear()、keys()、values()、entries、forEach()等等。

ES6学习总结之Set和Map数据结构的理解的更多相关文章

  1. ES6学习笔记(10)----Set和Map数据结构

    参考书<ECMAScript 6入门>http://es6.ruanyifeng.com/ Set和Map数据结构 1.Set  基本用法    Set是一种新的数据结构,它的成员都是唯一 ...

  2. ES6 学习笔记(十)Map的基本用法

    1 基本用法 Map类型是键值对的有序列表,而键和值都可以是任意类型.可以看做Python中的字典(Dictionary)类型. 1.1 创建方法 Map本身是一个构造函数,用来生成Map实例,如: ...

  3. js ES6 Set和Map数据结构详解

    这篇文章主要介绍了ES6学习笔记之Set和Map数据结构,结合实例形式详细分析了ECMAScript中基本数据结构Set和Map的常用属性与方法的功能.用法及相关注意事项,需要的朋友可以参考下   本 ...

  4. ES6中的Set与Map数据结构

    本文实例讲述了ES6学习笔记之Set和Map数据结构.分享给大家供大家参考,具体如下: 一.Set ES6提供了新的数据结构Set.类似于数组,只不过其成员值都是唯一的,没有重复的值. Set本身是一 ...

  5. ES6中map数据结构学习

    在项目中遇到一个很恶心的需求,然后发现ES6中的map可以解决,所以简单学习了一下map. Javascript的Object本身就是键值对的数据结构,但实际上属性和值构成的是“字符串-值”对,属性只 ...

  6. ES6中Map数据结构学习笔记

    很多东西就是要细细的品读然后做点读书笔记,心理才会踏实- Javascript对象本质上就是键值对的集合(Hash结构),但是键只能是字符串,这有一定的限制. 1234 var d = {}var e ...

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

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

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

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

  9. es6 学习7 Set 和 Map 数据结构

     Set 和 Map 数据结构 一.Set ES6 提供了新的数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. const set = new Set([1, 2, 3, 4, ...

随机推荐

  1. PHP小补充

    code1-1 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> < ...

  2. lightoj 1061 - N Queen Again(状压dp)

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1061 题解:显然能满足情况的8皇后的摆法不多,于是便可以用题目给出的状态来匹配 ...

  3. 大白话通俗易懂的讲解javascript原型与原型链(__proto__、prototype、constructor的区别)

    javascript原型和原型链是js中的重点也是难点,理论上来说应该是属于面向对象编程的基础知识,那么我们今天为什么要来讲这个呢?(因为我也忘了,最近看资料才揭开面纱……  哈哈哈) 好了,直接进入 ...

  4. 告别组件之教你使用原生js和css写移动端轮播图

    在工作中由于项目需要要写一个轮播图,本想使用组件直接调用实现快速开发,但是一想到自己经常使用组件但是让自己手写的话确实一点都不会. 一个不会手写组件的前端程序员不是一个好程序员!于是打算自己手写一个. ...

  5. DAX 第八篇:表连接

    表连接是指两张表根据关联字段,组合成一个数据集.表连接不仅可以利用数据模型中已有的关系,而且可以利用DAX表达式基于表的任意列定义连接条件.因此,在DAX中,实现表与表之间的连接,有两种方式: 第一种 ...

  6. JS数组方法整理(附使用示例)

    整理目前所用过的数组方法,学习了新增的es6方法. 1.arr.push() 从后面添加元素,返回值为添加完后的数组的长度 let arr = [1,2, is 8.3,4,5] console.lo ...

  7. redis在windows下安装设置密码及主从数据库

    redis在windows下安装设置密码及主从数据库 1.安装 下载解压后,如图所示: 2.配置. 打开redis.windows.conf文件,在此处设置端口和ip: 这里设置持久化: 在这里设置密 ...

  8. Spring Boot2 系列教程(五)Spring Boot中的 yaml 配置

    搞 Spring Boot 的小伙伴都知道,Spring Boot 中的配置文件有两种格式,properties 或者 yaml,一般情况下,两者可以随意使用,选择自己顺手的就行了,那么这两者完全一样 ...

  9. <xsl:apply-templates>和<xsl:call-template>的区别

    <xsl:apply-templates> 应用模板,故名思意,将定义好的模板应用到 XML 的节点上.  可以调用 XML 文档的节点,使 XSL 文档可以渲染 XML 元素内的数据,  ...

  10. Docker Compose部署项目到容器-基于Tomcat和mysql的商城项目(附源码和sql下载)

    场景 Docker-Compose简介与Ubuntu Server 上安装Compose: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/deta ...