Set 和 WeakSet用法
(1)什么是set
Set是ES6给开发者带来的一种新的数据结构,你可以理解为值的集合。我们平时见到的数组Array也是一种数据结构,但是Set跟其他数据结构不同的地方就在于:它的值不会有重复项。
(2)、set的基本用法
let set = new Set() set他的值不会重复 所以自动去了重
let set = new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9])
console.log(set);
Set本身是一个构造函数,你可以理解为一个类,使用的时候需要用new来创建一个实例。以上的案例就是这样创建出一个Set结构,我们打印出来看看,控制台输出:Set{ }。
set.add(110, 111, 112, 113, 111, 111, 111, 111, 111, 111) //只加进去了110
set.add(111)
set.add(112)
console.log(set);
它不是值的集合吗,那如果我们想给Set对象增加一些值成员,你可以
var s = new Set([1,2,3]);
console.log(s);
//打印结果:Set {1, 2, 3}
用数组[ 1,2,3 ]作为参数传入,得到的变量s为Set { 1, 2, 3 }。
除了上面的方法,你还可以这样:
s.add(111)
s.add(112)
console.log(s);
如果你不想用数组作为参数来传值初始化变量s,你还可以通过Set 结构提供的add方法来添加方法,也是没问题的。
成员值唯一
不过,为Set 结构添加成员值的时候,要注意一点是,set结构的成员值是没有重复的,每个值都是唯一的,如果人为地给它添加相同的成员值
console.log(s.add(911));
console.log(s); //显示有13个内容
console.log(s.add(911));
console.log(s); //还是有13个内容
如果里面已经有一个内容,在加入相同的内容时不会成功
size属性:获取成员的个数。
console.log(set.size);
delete( )方法:用户删除Set结构中的指定值,删除成功返回:true,删除失败返回fasle。
console.log(s.delete(911)); //true
console.log(s.delete(1120)); //false
console.log(s);
clear( )方法:清除所有成员。
s.clear()
console.log(s);
has()方法:判断set结构中是否含有指定的值。如果有,返回true;如果没有,返回fasle。
console.log(s.has(111)); //true
console.log(s.has(1120)); //false
entries()方法:返回一个键值对的遍历器。
console.log(s.entries());
// 注意得到的结果,成员值“a”对应的键值对是[“a”,”a”],也就是说:Set结构是键名和键值是同一个值。
keys和values方法
// keys()方法:返回键名的遍历器。
// values()方法:返回键值的遍历器。
console.log(set.keys());
console.log(set.values());
foreach方法 forEach()方法:遍历每一个成员。
set.forEach(function (value, key) {
console.log(value, key)
});
// 使用方式跟数组的forEach一样。当然,得到的value是key的值是一样的。
et用途之一
// 利用Set结构的成员值不能重复的特点,我们可以轻松的完成数组去重
var arr = [1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6]
let s = new Set(arr); //利用Set结构的成员值不能重复的特点去重
let ss = Array.from(s); //转化成数组
console.log(ss);
上面的代码重点是一个含有重复元素的数组,作为参数,用于初始化一个Set实例对象,因为Set结构不会含有重复成员,就会自动忽略相同的元素,只保留一个相同的值。
Weakset结构
// 讲到Set结构,就不能不讲WeakSet结构。Set和WeakSet两者名字就很像,注定它们有很多一样的地方。
// WeakSet结构同样不会存储重复的值,不同的是,它的成员必须是对象类型的值。
//初始化一个WeakSet对象
let ws = new WeakSet([{ "age": 18 }]);
//结果:WeakSet {Object {age: 18}}
// 我们初始化一个WeakSet对象,参数一个数组,数组的成员必须是对象类型的值{ "age": 18 },否则就会报错
//初始化一个WeakSet对象
// let ws0 = new WeakSet([1, 2]);
//结果:报错
// 以上的写法就会报错,因为数组的元素不是对象类型的,是数字1, 2。
// 实际上,任何可遍历的对象,都可以作为WeakSet的初始化参数。比如:数组。
let arr1 = [1];
let arr2 = [2];
//初始化一个WeakSet对象,参数是数组类型
let wxs = new WeakSet([arr1, arr2]);
//结果:WeakSet {Array(1) [1] Array(1) [2]}
// 同样,WeakSet结构也提供了add() 方法,delete ( ) 方法,has()方法给开发者使用,作用与用法跟Set结构完全一致。
// 另一个不同点是:WeakSet 结构不可遍历。因为它的成员都是对象的弱引用,随时被回收机制回收,成员消失。所以WeakSet结构不会有keys(),values(),entries(),forEach()等方法和size属性。
_____________________________________________________________________________
Map和WeakMap用法
什么是Map?
介绍什么是Map,就不得不说起Object对象,我们都知道Object对象是键值对的集合:
{"name":"前端君","gender":1}
ES5中的key键名的类型要求一定是字符串,当然,ES6已经允许属性名的类型是Symbol。在,ES6 提供了Map结构给我们使用,它跟Object对象很像,但是不同的是,它的key键名的类型不再局限于字符串类型了,它可以是各种类型的值;可以说,它比Object对象更加灵活了,当然,也更加复杂了。
Map的基本用法
Map结构提供了一个构造函数给我们,我们使用的时候需要用new来创建实例
let m = new Map()
如果想要在创建实例的同时,初始化它的内容,我们可以给它传参,形式跟Set结构类型,都是需要用数组作为参数
let m = new Map([
["name","前端君"],
["gender",1]
]);
console.log(m);
注意Map( )方法里面的参数,首先它是一个数组,而里面的内容也是由多个数组组成,“name”:“前端君”作为一个键值对,将它们装在一个数组里面,[“name”:“前端君”],另外一组键值对也一样:[“gender”:1 ]。这就是初始化一个Map结构实例的基本写法。
Map的方法
set()
set( )方法作用:给实例设置一对键值对,返回map实例。
set方法添加一个string类型的键名
m.set("nam", "aaa");Map(4) {'name' => '前段君', 'age' => 18, 'nam' => 'aaa'}
//添加一个数字类型的键名
m.set(1, 2)
console.log(m)
set方法的使用很简单,只需要给方法传入key和value作为键名和键值即可。注意:第三行代码中,我们传入的key是数字1,这就证明了,Map结构确实可以存储非字符串类型的键名,当然你还可以设置更多其它类型的键名
//数组类型的键名
m.set([1], 2);
//对象类型的键名
m.set({ "name": "tetls" }, 2);
//布尔类型的键名
m.set(true, false);
//Symbol类型的键名
m.set(Symbol('name'), 1);
//null为键名
m.set(null, 1);
//undefined为键名
m.set(undefined, 1)
console.log(m);
使用set方法的时候有一点需要注意,如果你设置一个已经存在的键名,那么后面的键值会覆盖前面的键值
let n = new Map();
n.set("一", 'qd君')
console.log(n); //Map(1) {'一' => 'qd君'}
n.set("一", "hd君")
console.log(n); //Map(1) {'一' => 'hd君'}
//在设置一次
n.set("一", 'qd君')
console.log(n); //Map(1) {'一' => 'qd君'}
get方法
get( )方法作用:获取指定键名的键值,返回键值。
let b = new Map([["name", "qd"]])
console.log(b.get('name')); //qd
console.log(b.get("age")); //undefined
get方法使用也很简单,只需要指定键名即可。获取存在对应的键值,如果键值对存在,就会返回键值;否则,返回undefined,
delete方法
delete( )方法作用:删除指定的键值对,删除成功返回:true,否则返回:false。
console.log(b.delete('weight')); //false
console.log(b);
clear方法
// 跟Set结构一样,Map结构也提供了clear()方法,让你一次性删除所有键值对。
// b.clear()
// console.log(b); //Map(0) {size: 0}
has()方法作用:判断Map实例内是否含有指定的键值对,有就返回:true,否则返回:false。
console.log(b.has('weight')); //false
console.log(b.has('name')); //true
entries方法
// entries()方法作用:返回实例的键值对遍历器。
// let v = new Map([
// ["name", "qd"]
// ["age", 19]
// ])
// for (let [key, value] of v.entries()) {
// console.log(key + ' ' + value);
// }
let nnn = new Map([
["name", "前端君"],
["age", 25]
]);
for (let [key, value] of nnn.entries()) {
console.log(key + ' ' + value);
}//name 前端君
// age 25
// 案例中的 nnn.entries() 返回键值对的遍历器,使用了for...of来遍历这个遍历器,得到的值分别赋值到key和value,然后控制台分别输出它们。
// keys和values方法
// keys()方法:返回实例所有键名的遍历器。
// values() 方法:返回实例所有键值的遍历器。
// 既然都是遍历器,那就用for...of把它们遍历出来吧:
let c = new Map([
["name", "前端君"],
["age", 25]
]);
//使用keys方法获取键名
for (let key of c.keys()) {
console.log(key); // name age
}
//打印结果:name
//age
//使用values方法获取键值
for (let value of c.values()) {
console.log(value); //前端君 25
}
// keys方法和values方法的使用方式一致,只是返回的结果不同。
// forEach方法
// 除了使用以上三个方法实现遍历以外,我们还可以使用forEach遍历每一个键值对:
let x = new Map([
["name", "前端君"],
["age", 25]
]);
x.forEach(function (value, key) {
console.log(key + ':' + value);
});
//打印结果:name:前端君
// age:25
// forEach方法接收一个匿名函数,给匿名函数传参value和key分别是Map实例的键名和键值
// size属性
// 其中一个常用的属性就是size:获取实例的成员数。
let z = new Map();
z.set(1, 3);
z.set('1', '3');
console.log(z.size) //2
// 什么是WeakMap?
// WeakMap结构和Map结构很类似,不同点在于WeakMap结构的键名只支持引用类型的数据。哪些是引用类型的值呢?比如:数组,对象,函数。
// 关于什么是引用类型,其中涉及到了传址和传值的区别,
// WeakMap的基本用法
// WeakMap结构的使用方式和Map结构一样:
// let wm = new WeakMap();
// 两者都是使用new来创建实例。如果添加键值对的话,我们同样是使用set方法,不过键名的类型必须要求是引用类型的值,我们来看看
let wm = new WeakMap();
//数组类型的键名
wm.set([1], 2);
//对象类型的键名
wm.set({ 'name': 'Zhangsan' }, 2);
//函数类型的键名
function fn() { };
wm.set(fn, 2);
console.log(wm);
// WeakMap { Array(1) => 2, ƒ => 2, {… } => 2 }
// [[Entries]]
// { Array(1) => 2 }
// { function fn() { } => 2 }
// { Object => 2 }
// 从打印结果可以看出,以上类型的键名都可以成功添加到WeakMap实例中。
// WeakMap与Map的区别?
// 如果是普通的值类型则不允许。比如:字符串,数字,null,undefined,布尔类型。而Map结构是允许的,这就是两者的不同之处,谨记。
// 跟Map一样,WeakMap也拥有get、has、delete方法,用法和用途都一样。不同地方在于,WeakMap不支持clear方法,不支持遍历,也就没有了keys、values、entries、forEach这4个方法,也没有属性size。
// 理由跟WeakSet结构一样:键名中的引用类型是弱引用,你永远不知道这个引用对象什么时候会被垃圾回收机制回收了,如果这个引用类型的值被垃圾机制回收了,WeakMap实例中的对应键值对也会消失。