ES6中的Map和Set详解
概览
本文主要介绍了 ES6新增的Set和Map 数据结构,对其特性和常见用法进行了梳理
一. Set
Set是ES6中新增的数据结构,它类似于数组,但是Set数据中的元素都是唯一的,没有重复值的;
Set构造函数参数:初始化参数的时候,参数必须是实现iterator接口的数据类型,否则会抛出异常;
const set = new Set([1,2,3]);
const set1 = new Set('1233');
const set2 = new Set(1);
//VM387:1 Uncaught TypeError: number 1 is not iterable (cannot read property Symbol(Symbol.iterator))
at new Set (<anonymous>)
at <anonymous>:1:12
属性和方法
- Set.prototype.add()方法
Set.prototype.add(value);
参数1 value:需要添加到set元素中的值,不能够添加重复值;
返回值:返回实例化对象Set本身;
var s1 = new Set([1, 2, 3]);
var s2 = s1.add(4);
console.log(s1); // Set {1, 2, 3, 4}
console.log(s1 === s2); // true
-
Set.prototype.has()方法
Set.prototype.has(value);
参数1 value:必填项,测试该值是否存在Set对象中;
返回值:布尔值,false表示不存在,true表示存在;
var s1 = new Set([1, 2, 3, 4]);
s1.has(4); // true
- Set.prototype.size
size属性将返回Set对象的元素个数;
// add方法可以链式调用
var mySet = new Set();
mySet.add(1).add(2).add(3);
mySet.size; // 3
- Set.prototype.delete()方法
Set.prototype.delete(value);
参数1 value:需要删除的元素;
返回值:成功删除返回true,否则返回false;
-
Set.prototype.clear()方法
clear()方法用来清空一个Set对象中的所有元素; -
Set遍历的方法
Set.prototype.keys()方法,Set.prototype.values()方法,Set.prototype.entires()方法
var s1 = new Set([1, 2, 3]);
var iterator = s1.keys();
var iterator = s1.values();
var iterator = s1.entries();
console.log(iterator.next());
keys和values返回的结果相同,Set中的key等于value,这也是新增时add只传一个参数的原因
应用场景
- 数组去重
var arr = [1, 2, 3, undefined,undefined,null,null, NaN, 1, 2, 3, NaN],
set = new Set(arr);
console.log([...set]);
2. 数组去重后的实现映射数组
set实例本身没有map,filter等数组属性
let set = new Set([1,2,3,4,5,6,7]);
let set2 = new Set([...set].map(value => value * 2));
let set = new Set([1,2,3]);
let set1 = new Set(Array.from(set, vlaue=>value * 2));
- 数组去重后,过滤返回新的数组
let set = new Set([1,2,3,4,5,6,7,1,2,3]);
let set2 = new Set([...set].filter(x => (x%2) == 0));
循环递归调用
const s1 = new Set([1])
s1.forEach(item => {s1.delete(1);s1.add(1);console.log('end')})
会一直循环调用forEach里面代码,不断打印end
二. Map
传统的对象属性键名为字符串,并能够真真正正的实现属性键 — 属性值的对应;ES6Map数据结构实现的出现,实现对象键名与键值一 一对应的关系;
- 传统ES5中对象的属性名以字符串的形式存在
var m = {};
var x = {id:1},
y = {id:2};
m[x] = 'foo';
m[y] = 'bar';
console.log(m);
console.log(m[x]); // bar
console.log(m[y]); // bar
会将属性先执行toString方法
2.基本用法
Map构造函数参数:必须已经部署iterator接口的数据结构;
此时构造函数参数中的每一个参数必须拥有双元的数组结构;
两种声明方式
1.
let map = new Map([['name', 'zhansan'], ['sex', 'male']]);
let items = [['name', 'zhansan'], ['sex', 'male']],
map = new Map();
items.forEach(function([key, value]){
map.set(key, value);
});
- Map遍历的方法
const map = new Map([['name','zhangsan'],['sex','male'],['age',20]]);
console.log(map.keys());
console.log(map.values());
console.log(map.entries());
- Map.prototype.set()
set()方法为Map对象添加或者更新一个指定键(key)和值(value)的新键值对;
var myMap = new Map();
// 添加元素
myMap.set("bar", "foo");
myMap.set(1, "foobar");
console.log(myMap);
// 更新元素
myMap.set("bar", 'goo');
console.log(myMap);
Map.set()设置属性时,属性名相同时,后面覆盖前面的键值;
Map键名覆盖的问题: 本质上与全等的运算方式类型,只是对待NaN问题上不同
const map = new Map();
map.set(-0, 123);
console.log(map.get(+0)); // 123
map.set(true,1);
map.set('true',2);
console.log(map.get(true)); // 1
map.set(NaN,123);
map.set(NaN,456);
console.log(map.get(NaN)); // 456
- Map.prototype.get()方法
get()方法返回某一个Map对象中的一个指定元素;
如果找不到相关的键名,则返回undefined;
注意不同的引用值数据类型作为键名,获取的数据不同;
// 引用地址不同的情况;
const map = new Map();
map.set([5], 555);
map.get([5]); // undefined
map.set({}, 555);
console.log(map.get({})); // undefined
// 引用地址相同的情况
var obj = {id:1};
const map = new Map();
map.set(obj, 'foo');
console.log(map.get(obj)); // 'foo'
- 和Set 对比
Map.prototype上的clear()、has()、size、delete()方法与Set.prototype上相同;唯一不同的是,Set是不存在键名的,键值与键名相同,所以没有get和set的方法,只有add方法;而Map具有键名和键值,所以对应set和get方法;