一、Set对象
Set
对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。
Set
对象是值的集合,你可以按照插入的顺序迭代它的元素。 Set中的元素只会出现一次,即 Set 中的元素是唯一的。
在 ECMAScript 2015规范中-0 0 +0 是完全相等的。
NaN
和undefined
都可以被存储在Set 中, NaN
之间被视为相同的值(NaN被认为是相同的,尽管 NaN !== NaN)。
Number.POSITIVE_INFINITY 和 Infinity都表示正无穷数,是相同的值。
引用值地址不能相同,原始值不能相等,这才能确保值的唯一性。
创建Set对象
1、可以接受一个数组,数组的@@iterator接口的每项值作为Set对象的每项值
let set = new Set([1,2,3,4])
set.add([3,4,5]);
console.log(set); Set(5) {1, 2, 3, 4, Array(3)}
2、其实可以接受任何符合格式的带有@@iterator接口的对象
接受字符串:
let set = new Set("abcd");
console.log(set); Set(4) {"a", "b", "c", "d"}
接收Set对象:
let set = new Set("abcd");
console.log(new Set(set)); Set(4) {"a", "b", "c", "d"}
接收Map对象:
let map = new Map([
[1,"a"],
[2,"b"]
])
console.log(new Set(map)) Set(2) {[1, "a"], [2,"b"]}
接收Iterator对象:
let set = new Set("abcd");
let map = new Map([
[1,"a"],
[2,"b"]
])
console.log(new Set(set.values())); Set(4) {"a", "b", "c", "d"}
console.log(new Set(map.values())) Set(2) {"a", "b"}
一、属性size
Size属性将会返回Set
对象中元素的个数。
size
的值是一个整数,表示Set
对象有多少条目。size
的集合访问函数是undefined
; 你不能改变这个属性值
let arr = [1,2,3,4];
let set = new Set(arr);
set.size = 2; //无效,但不报错
console.log(set.size);// 4
二、方法
(1)add方法
add()
方法用来向一个 Set
对象的末尾 添加一项指定的值。add方法返回该Set对象,所以可以链式调用。
注意:添加重复的值是无效的。
let arr = [3,4];
let mySet = new Set();
mySet.add(1)
.add("a")
.add([3,4])
.add({name:"zhu"})
.add(arr)
.add(NaN)
.add(undefined)
console.log(mySet);
(2)has方法
has() 方法返回一个布尔值来指示对应的值value是否存在Set对象中。
let arr = [1,2,3,4,NaN];
let set = new Set(arr);
console.log(set.has(NaN)); //true
(3)values方法、keys方法、entries方法 都返回SetIterator对象
let arr = ["a","b","c"];
let mySet = new Set(arr);
console.log(mySet); //Set(3) {"a", "b", "c"}
console.log(mySet.keys()) //SetIterator {"a", "b", "c"}
console.log(mySet.values()) //SetIterator {"a", "b", "c"}
console.log(mySet.entries())//SetIterator {"a" => "a", "b" => "b", "c" => "c"}
values()
方法返回一个 Iterator
对象,该对象按照原Set 对象元素的插入顺序返回其所有元素。兼容性Egde12。
下面两个方法兼容性不好,Set对象判断值唯一,算不上有键,keys方法和entries方法得到的结果都与键有关,与Set本意不符。
keys()
方法是value()方法的别名 (与 Map
对象相似); 它的行为与 value 方法完全一致,返回 Set 对象的元素。
entries() 方法返回一个新的迭代器对象 ,这个对象的元素是类似 [value, value] 形式的数组,value 是集合对象中的每个元素,迭代器对象元素的顺序即集合对象中元素插入的顺序。由于集合对象不像 Map 对象那样拥有 key,然而,为了与 Map 对象的 API 形式保持一致,故使得每一个 entry 的 key 和 value 都拥有相同的值,因而最终返回一个 [value, value] 形式的数组。
与Map对象相比,Set对象的keys values entries方法得到的也是iterator对象。而Set对象这些方法都在处理Set对象的value值,keys得到的value,values得到是value,entries得到的是value作为键和value作为值。
返回值:一个新的包含 [value, value] 形式的数组迭代器对象,value 是给定集合中的每个元素,迭代器 对象元素的顺序即集合对象中元素插入的顺序。
(4)forEach方法
在forEach的处理函数中value和key都是value值
let arr = [3,4];
let mySet = new Set();
mySet.add(1)
.add("a")
.add([3,4])
.add({name:"zhu"})
.add(arr)
.add(NaN)
.add(undefined)
console.log(mySet);
mySet.forEach((value, key) => {
console.log(value);
})
(5)delete方法
delete()
方法可以从一个 Set
对象中删除指定的元素。成功删除返回 true
,否则返回 false。
let set = new Set("abcd");
set.delete("a");
console.log(set); Set(3) {"b", "c", "d"}
(6)clear方法
let set = new Set("abcd");
set.clear();
console.log(set); Set(0) {}
三、Map对象和Set对象与数组之间的转换
1、Set对象和Map对象都可以转换为数组
Set对象转数组:得到是Set对象的value值组成的数组。
let arr = ["a","b","c"];
let mySet = new Set(arr);
console.log(mySet); //Set(3) {"a", "b", "c"}
console.log([...mySet]); //["a","b","c"]
1)、展开运算符,将Set对象展开后,放在【】中,我们知道Set对象的结构:
Set(3) {"a", "b", "c"}
我们可以使用展开运算符先将其展开,再用[]包裹,其实是将值放在数组中。
2)、也可以直接通过Array.from方法,将Set对象转换为数组。
Map对象转数组,也是这两种方式:得到的也是数组,该数组的每项都是一个长度为2的数组,第一项是key值,第二项是value值。
let myMap = new Map();
myMap.set("name", "zhuzhu")
.set(23, 24)
.set(false, true)
.set(["1",2], ["js","html","css"])
.set({}, {a:1,b:2});
console.log([...myMap]); [Array(2), Array(2), Array(2), Array(2), Array(2)]
console.log(Array.from(myMap));[Array(2), Array(2), Array(2), Array(2), Array(2)]
2、数组转Map对象和Set对象
1)数组转Set对象,且会去重:
let arr = ["a",1,"b",2,2];
let mySet = new Set(arr);
console.log(mySet); Set(4) {"a", 1, "b", 2}
2)数组转Map对象,必须是二维数组:
let arr = [["a",1],["b",2],["c",3]];
let myMap = new Map(arr);
console.log(myMap); Map(3) {"a" => 1, "b" => 2, "c" => 3}
四、Set和Map的实例应用
1、Map对象的应用
(1)Map对象的克隆(浅克隆)
arr和myMap中的arr和cloneMap中的arr指向同一个地址。
let myMap = new Map();
let arr = [1,2,3];
myMap.set("name", "zhuzhu")
.set(23, 24)
.set(false, true)
.set(arr, ["js","html","css"])
.set({}, {a:1,b:2});
let cloneMap = new Map(myMap);
console.log(cloneMap === myMap); //false 浅克隆,不是同一个地址
arr[0] = "a";
console.log(myMap); //myMap中的arr指向的地址值被修改
console.log(cloneMap) //cloneMap中的arr指向的地址值被修改
当arr的索引被修改时,不影响myMap和cloneMap中的arr索引地址
let myMap = new Map();
let arr = [1,2,3];
myMap.set("name", "zhuzhu")
.set(23, 24)
.set(false, true)
.set(arr, ["js","html","css"])
.set({}, {a:1,b:2});
let cloneMap = new Map(myMap);
console.log(cloneMap === myMap); //false 浅克隆,不是同一个地址
arr = ["a"];
console.log(myMap); //myMap没有被修改
console.log(cloneMap) //cloneMap没有被修改
(2)Map对象的合并
var first = new Map([[1, 'one'], [2, 'two'], [3, 'three']]);
var second = new Map([[1, 'uno'], [2, 'dos']]);
// 合并两个 Map 对象时,如果有重复的键值,则后面的会覆盖前面的,对应值即 uno,dos, three
var merged = new Map([...first, ...second]);
console.log(merged); Map(3) {1 => "uno", 2 => "dos", 3 => "three"}
2、Set对象的应用
(1)数组去重
根据Set对象的唯一性和Set对象与数组之间的转换,进行数组去重
let arr = [1,2,3,4,3,2,1];
let mySet = new Set(arr);
console.log([...mySet]); [1, 2, 3, 4]
(2)数组的并集
去重后的数组arr1,进行过滤操作,过滤每一项的时候,arr1不存在另一个arr2数组中的项组成的数组和arr2合并
let arr1 = [1,2,3,4,3,2,1];
let arr2 = [3,4,2,5,8,9];
let set1 = new Set(arr1);
let set2 = new Set(arr2);
let mergeArr = ([...set1].filter(item => !set2.has(item))).concat([...set2]);
console.log(mergeArr); [1, 3, 4, 2, 5, 8, 9]
(3)数组的交集
去重后的arr1和arr2,arr1进行过滤,arr2中也有项组成的数组就是交集
let arr1 = [1,2,3,4,3,2,1];
let arr2 = [3,4,2,5,8,9];
let set1 = new Set(arr1);
let set2 = new Set(arr2);
let mergeArr = [...set1].filter(item => set2.has(item));
console.log(mergeArr) [2, 3, 4]
(4)数组的差集
去重后的arr1和arr2,arr1进行过滤,arr2中没有的项组成的数组和arr2进行过滤,arr1中没有的项组成的数组进行合并
let arr1 = [1,2,3,4,3,2,1];
let arr2 = [3,4,2,5,8,9];
let set1 = new Set(arr1);
let set2 = new Set(arr2);
let mergeArr = ([...set1].filter(item => !set2.has(item))).concat([...set2].filter(item => !set1.has(item)))
console.log(mergeArr); [1, 5, 8, 9]