Set
ES6提供了新的数据结构Set。它类似于数组。但是成的值都是唯一的,没有重复的值。
Set本身是一个构造函数,用来生成Set数据结构。
可以用来数组的去重。
向Set加入值的时候,不会发生类型的转换,所以5和‘5’是两个不同的值。Set内部 判断两个值是否不同使用的算法类似于精确相等运算符(===),于‘===’的主要的区别的NaN等于自身 而‘===’ NaN是不等于自身的。
对象基于指针问题 是不会相等的。
const s = new Set();
[2,3,4,5,6,4,3,4,2,2].forEach(x => s.add(x));
for(let i of s){
console.log(i);
}
//2,3,4,5,6
const set = new Set([1,2,3,4,4])
[...set]
//1,2,3,4
let set = new Set();
let a = NaN;
let b = NaN;
set.add(a);
set.add(b);
set //Set{NaN};
Set实例的属性和方法
Set.prototype.constructor //指向本身
Set.prototype.size //Set实例的成员总数
方法:
add() //增加
delete() //删除
has() //查询 返回Boolean
clear() //清除所有
遍历方法:
keys()//返回键名
values()//返回键值
entries()//返回键值对数组
forEach() //loop
由于Set结构没有键名,只有键值所以keys和values方法的行为完全一致。
let set = new Set(['red', 'green', 'blue']);
for(let item of set.keys()){
console.log(item);
// red
// green
// blue
}
for(let item of set.values()){
console.log(item);
// red
// green
// blue
}
for(let item of set.entries()){
console.log(item);
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]
}
//所以set的value获取直接可以用for...of获取
for(let item of set){
console.log(item);
// red
// green
// blue
}
//Set结构的实例于数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值
set.forEach((key,value) => {console.log(key + ' : ' + value)});
// red:red
// green:green
// blue:blue
运用扩展运算符
let set = new Set(['red', 'green', 'blue']);
[...set]
//['red','green','blue']
//扩展运算符与Set结构相结合,就可以去除数组的重复成员
let set = [1,2,3,3,3,3,4,4,5];
[...new Set(set)]
//[1,2,3,4,5]
new Set([...set].filter(x => {return x % 2 === 0}));
//{2,4}
Set 实现并集/交集/差集
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([...a].filter(x => !b.has(x)));
//Set{1}
改变Set值
let set = new Set([1,2,3]);
set = new Set([...set].map(x => x*2));
//Set{2,4,6}
set = new Set(Array.from(set,x => x * 2));
//Set{2,4,6}
WeakSet
WeakSet结构与Set相似,也是不重复的值的集合。但是它与Set有两个区别。
首先WeakSet的成员只能是对象,而不能是其他类型的值。其中的对象都是弱引用,随时可能小时,跟浏览器垃圾回收机制有关。不会出现内存泄漏。
比较适合临时存放一组对象,以及存放跟对象绑定的信息。
方法:add() delete() has()
WeakSet不可遍历所以也没有size属性
const ws = new WeakSet();
ws.add(1)
//TypeError:Invalid value used in weak set
ws.add(Symbol());
//TypeError:Invalid value used in weak set
具有Iterable接口的对象,都可以作为WeakSet的参数。
b数组的成员为WeakSet的成员,而不是b数组本身。这意味着,数组的成员只能是对象。
const a = [[1,2],[3,4]];
const ws = new WeakSet(a);
//WeakSet{[1,2],[3,4]}
const b = [1,2];
const ws = new WeakSet(b);
//uncaught TypeError:Invalid value used in weak set;
Map
Javascript的对象(Object),本质上是键值对的集合(Hash结构),但是传统上只能用字符串当作键。
Map数据结构类似于对象,也是键值对的集合,但是与对象的区别是键的繁为不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说Object结构提供了‘字符串-值’的对象,Map结构提供了‘值-值’的对象。这是一种更完善的Hash结构实现。如果你需要‘键值对’的数据结构,Map比Object更合适。
属性:size 返回Map结构的成员总数
方法:set get has delete clear
//Map结构数据的增删改查。
const m = new Map();
const o = {p:'hello world'};
m.set(o,'content');
m.get(o)//content
m.has(o)//true
m.delete(o)//true
m.has(o)//false
m.clear();
m.size //0
遍历的方法 keys values entries forEach
//Map数据结构可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。
const map = new Map([
['name', '张三'],
['title', 'Author']
]);
map.size //2
map.has('name')//true
map.get('name')//'张三'
map.has('title')//true
map.get('title')//'Author'
//上面的例子解析执行的方法
const items = [
['name', '张三'],
['title', 'Author']
]
const map = new Map()
items.forEach(([key,value]) => map.set(key,value))
Set和Map都可以用来生成新的Map
const set = new Set([
['foo',1],
['bar',2]
]);
const m1 = new Map(set);
m1.get('foo')//1
const m2 = new Map([['bar',3]]);
const m3 = new Map(m2);
m3.get('bar')//3
m3.set('bar',4)
m3.get('bar')//4 如果对同一个键多次赋值,后面的值将覆盖前面的值
new Map().get('sdfsdf')//undefined
//如果键为对象要确定为同一个对象的引用
const map = new Map()
map.set(['a'],555);
map.get(['a']);//undefined
//同理,同样的值的两个实例,在Map结构中被视为两个键
const map = new Map()
var a = ['a'];
var b = ['a']
map.set(a,555);
map.set(b,666)
map.get(a);//555
map.get(b);//666
Map通过严格相等来判断是否为一个键。
0 === -0//true
true === 'true' //false
undefined === null //false
NaN === NaN //false 虽然NaN不严格相等于自身,但Map将其视为同一个键
Map与其他数据结构的互相转换
Map转为数组
const map = new Map([
['F', 'no'],
['T', 'yes'],
]);
[...map]
数组转为Map
new Map([...map])
Map转为对象
function Maptoobj(v){
var obj = Object.create(null);
for(let [key,value] of v){
obj[key] = value
}
return obj
}
Maptoobj(map);
对象转化为Map
function objtomap(v){
var map = new Map();
for(let i of Object.keys(v)){
map.set(i,v[i])
}
return map
}
objtomap({'a':1})
Map 转化为Json 如果Map的键名都是字符串
function maptojson(v){
return JSON.stringify(Maptoobj(v))
}
let myMap = new Map().set('yes', true).set('no', false);
maptojson(myMap)
// '{"yes":true,"no":false}'
如果Map的键名有非字符串
function mapToArrayJson(map) {
return JSON.stringify([...map]);
}
let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
mapToArrayJson(myMap)
// '[[true,7],[{"foo":3},["abc"]]]'
JSON转化为Map
function jsonToStrMap(jsonStr) {
return objtomap(JSON.parse(jsonStr));
}
jsonToStrMap('{"yes": true, "no": false}')
// Map {'yes' => true, 'no' => false}
如果整个json是一个数组且每个数组成员本身又是一个又两个成员的数组
function jsonToMap(jsonStr) {
return new Map(JSON.parse(jsonStr));
}
jsonToMap('[[true,7],[{"foo":3},["abc"]]]')
// Map {true => 7, Object {foo: 3} => ['abc']}
WeakMap
与Map数据结构类似,也是用于生成键值对的集合 与Weakset一样突出弱引用的作用。
与Map的区别
1.和WeakSet一样只接受对象作为键名(null除外,null为对象 但是null不可以作为键名),不接受其他类型的值作为键名。
const map = new WeakMap();
map.set(1,2)
//TypeError :1 is not an Object!
map.set(Symbol(),2)
//TypeError:Invalid value used as weak map key
map.set(null,2)
//TypeError:invalid value used as weak map key
与WeakSet一样 WeakMap没有遍历操作(即没有keys() values() entries()方法)也没有size属性。也不支持clear()方法。
const wm = new WeakMap()
wm.size //undefined
wm.clear//undefined
wm.forEach//undefined