ES6 Set、Map

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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。