笔者最近在深刻学习ES6中, 在写代码的过程当中用到了set,Map这两个ES6新增的数据结构, 深切感觉到了它们的强大, 解决问题的能力。因而笔者决定写一篇文章总结一下。并分享给你们,但愿可以对你们有帮助。这篇文章主要给你们介绍了关于ES6学习笔记之map、set与数组、对象对比的相关资料, 下面让咱们一块儿走进set, Map的世界吧😄😄。html
舒适提示: Map和Set是ES6标准新增的数据类型,请根据浏览器的支持状况决定是否要使用。前端
JavaScript的默认对象表示方式{}能够视为其余语言中的Map或Dictionary的数据结构,即一组键值对。 可是JavaScript的对象{}有个小问题,就是键必须是字符串。但实际上Number或者其余数据类型做为键也是很是合理的。 为了解决这个问题,最新的ES6规范引入了新的数据类型Map。git
Object是字符串-值,Map是值-值es6
// 初始化
let key1 = 12;
let value1 = 'test';
let m1 = new Map(); // m1: Map {}
let m2 = new Map([[key1, value1]]); // m2: Map { 12 => 'test' }
复制代码
let m2 = new Map([['ou', 'yang'],['xing', 'hua']]);
console.log(m2.size) //输出2
复制代码
var m = new Map(); // 空Map
m.set('ouyang', 21); // 添加新的key-value
console.log(m); //Map { 'ouyang' => 21 }
m.set('ouyang', 22)
console.log(m); //Map { 'ouyang' => 22 }
复制代码
注意:因为一个key只能对应一个value,因此,屡次对一个key放入value,后面的值会把前面的值冲掉。github
let m2 = new Map([[12, 'yang']])
console.log(m2.get(12)) // 返回yang
复制代码
let m2 = new Map([[12, 'yang']])
console.log(m2.has(12)); // true
console.log(m2.has(13)); // false
复制代码
let m2 = new Map([[12, 'yang']])
m2.delete(12)
console.log(m2) // Map {}
复制代码
let m2 = new Map([[12, 'yang'],['xing', 'hua']])
m2.clear()
console.log(m2) // Map {}
复制代码
在此以前有必要说一下迭代器的做用, 迭代器是一种特殊对象,这种对象具备如下特色:数组
1,全部对象都有一个next方法 2,每次调用next方法,都会返回一个对象,该对象包含两个属性,一个是value, 表示下一个将要返回的值。另外一个是done,他是一个布尔值,用来表示该迭代器是否还有数据能够返回. 3,迭代器还会保存一个内部指针指向当前集合中的值浏览器
想深刻了解迭代器的点这里bash
let m2 = new Map([[12, 'yang'],['xing', 'hua']])
var iterator1 = m2.keys();
console.log(iterator1); //[Map Iterator] { 12, 'xing' }
console.log(iterator1.next().value); // 12
console.log(iterator1.next().value); // xing
复制代码
let m2 = new Map([[12, 'yang'],['xing', 'hua']])
console.log(m2.values()) // [Map Iterator] { 'yang', 'hua' }
复制代码
let m2 = new Map([[12, 'yang'],['xing', 'hua']])
var iterator1 = m2.entries();
console.log(iterator1); //[Map Iterator] { [ 12, 'yang' ], [ 'xing', 'hua' ] }
复制代码
myMap.forEach(callback[, thisArg])数据结构
1.必要参数, callback为每一个元素所要执行的函数。 2.可选参数, callback执行时其 this 的值。函数
callback 函数有三个参数
1.value -元素的值 2.key -元素的键 3.Map -当前正在被遍历的对象
下面请看看例子
let Data = new Map();
let objKey = { num:10 };
let obj = {
num:5
}
Data.set("a", 1);
Data.set("b", 2);
Data.set("c", 3);
Data.forEach(function (value,key) {
console.log(value*this.num); // 输出5 10 15
}, obj)
复制代码
从上面的代码能够看出回调函数中this指向obj对象。
Map 转为数组最方便的方法,就是使用扩展运算符(...)。
const myMap = new Map()
.set(true, 7)
.set({foo: 3}, ['abc']);
[...myMap] // 输出 [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]
复制代码
将数组传入 Map 构造函数,就能够转为 Map。
new Map([
[true, 7],
[{foo: 3}, ['abc']]
])
// Map {
// true => 7,
// Object {foo: 3} => ['abc']
// }
复制代码
若是全部 Map 的键都是字符串,它能够无损地转为对象。
function strMapToObj(strMap) {
let obj = Object.create(null);
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 }
复制代码
若是有非字符串的键名,那么这个键名会被转成字符串,再做为对象的键名。
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})
// Map {"yes" => true, "no" => false}
复制代码
结合数组的map方法、filter方法,能够实现 Map 的遍历和过滤(Map 自己没有map和filter方法)。
const map0 = new Map()
.set(1, 'a')
.set(2, 'b')
.set(3, 'c');
const map1 = new Map(
[...map0].filter(([k, v]) => k < 3)
);
// 产生 Map 结构 {1 => 'a', 2 => 'b'}
const map2 = new Map(
[...map0].map(([k, v]) => [k * 2, '_' + v])
);
// 产生 Map 结构 {2 => '_a', 4 => '_b', 6 => '_c'}
复制代码
写到这里,Map的基本用法和应用以及讲完了,我相信应该能够知足你们平常使用的需求吧。下面来看看set数据结构吧~~
- ES6 提供了新的数据结构 Set。它相似于数组,可是成员的值都是惟一的,没有重复的值。Set 自己是一个构造函数,用来生成Set数据结构。
- Set和Map相似,也是一组key的集合,但不存储value。因为key不能重复,因此,在Set中,没有重复的key。
都是一个存储多值的容器,二者能够互相转换,可是在使用场景上有区别。以下:
const s = new Set();
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x)) //添加元素;
for (let i of s) {
console.log(i);
}
// 2 3 5 4
复制代码
Set 函数能够接受一个数组(或者具备 iterable 接口的其余数据结构)做为参数,用来初始化。 特色:
// 以数组为参数
const set = new Set([1, 2, 3, 4, 4, '4'])
[...set] // [1, 2, 3, 4, '4']
set.size // 5
// 一个相似数组的带 iterable 接口的对象
const set = new Set(document.querySelectorAll('div'))
复制代码
Set 实例的属性和方法和Map 实例的属性和方法相似,下面简要介绍一下。
const s = new Set();
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x)) //添加元素;
console.log(s.size) // 由于不能有重复元素因此输出4
复制代码
因为Set只有key,并不存储value(或者说键名和键值是同一个值),因此相对Map少了get()方法
const s = new Set()
s.add(1).add(2).add(2)
console.log(s) // Set { 1, 2 }
s.size // 2
s.has(1) // true
s.has(2) // true
s.has(3) // false
s.delete(2)
console.log(s) //Set { 1 }
s.size // 1
s.has(2) // false
复制代码
方法名和Map的遍历方法名同样,下面来看用法
keys方法、values方法、entries方法返回的都是遍历器对象。因为 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),因此keys方法和values方法的行为彻底一致。
const set = new Set(['a', 'b', 'c']);
for (let item of set.keys()) {
console.log(item); // a b c
}
for (let item of set.values()) {
console.log(item); // a b c
}
for (let item of set.entries()) {
console.log(item);
}
// 由于键名和键值是同一个值,因此输出下面内容
// ["a", "a"]
// ["b", "b"]
// ["c", "c"]
set.forEach((value, key) => console.log(key + ' : ' + value))
// a: a
// b: b
// c: c
复制代码
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
// 并集
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}
// 交集
let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}
// 差集
let difference = new Set([...union].filter(x => !intersect.has(x)));
// Set {1}
复制代码
若是想在遍历操做中,同步改变原来的 Set 结构,目前没有直接的方法,但有两种变通方法。
// 方法一
let set = new Set([1, 2, 3]);
set = new Set([...set].map(val => val * 2));
// set的值是2, 4, 6
// 方法二
let set = new Set([1, 2, 3]);
set = new Set(Array.from(set, val => val * 2));
// set的值是2, 4, 6
复制代码
因为Set中元素的独一无二,根据内存地址来进行判断,因此若是有多个元素是引用型的话,尽管值相同,可是内存地址不一样,那么在Set对象中也将会存储多份,和Map相似
let set = new Set([1, 2, 3, 3, 4]);
let arr = Array.from(set) //输出[1,2,3,4]
复制代码
var arr = [55, 44, 65];
var set = new Set(arr);
console.log(set) // Set { 55, 44, 65 }
console.log(set.size === arr.length);
console.log(set.has(65));
复制代码
经过笔者的解析,发现Set、Map这两种ES6新增的数据结构在必定程度解决了Object和Array的一些痛点。他让咱们在选择数据结构去解决具体问题时又多了两种选择,在开发过程当中,涉及到数据结构,能使用Map不使用数组,尤为是复杂的数据结构。若是数据的要求比较高,强调惟一性,就使用Set,放弃使用Object作存储。在数据结构中优先考虑Map、Set,放弃数组和Object。不过何时使用仍是要看应用场景的啦😄。但愿这篇文章可以对你们有所帮助😄。
最后允许小生附上个人github地址 里面记录了我学习前端的点点滴滴,以为有帮助的小哥哥小姐姐能够给个小星星哟😄