美文网首页
ES6中的Map和Set

ES6中的Map和Set

作者: 肥羊猪 | 来源:发表于2021-03-02 09:17 被阅读0次

Set函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化。

// 例一
var set = new Set([1, 2, 3, 4, 4]);
[...set]
// [1, 2, 3, 4]
 
var s = new Set();
 
[2, 3, 5, 4, 5, 2, 2].map(x => s.add(x));
 
for (let i of s) {
 console.log(i);
}
// 2 3 5 4

注:在Set内部,两个NaN是相等。两个对象总是不相等的。可以用length来检测

let set = new Set();
let a = NaN;
let b = NaN;
set.add(a);
set.add(b);
set // Set {NaN}
let set = new Set();
 
set.add({});
set.size // 1
set.add({});
set.size // 2

var arr=[
    {id:1,name:'qqq'},
    {id:2,name:'qqq'},
    {id:3,name:'qqq'},
    {id:4,name:'qqq'},
    {id:2,name:'qqq'}
]
const s = new Set();
arr.forEach(x => s.add(x));
for (let i of s) {
 console.log(i);
}
// {id:1,name:'qqq'},
 //   {id:2,name:'qqq'},
 //   {id:3,name:'qqq'},
  //  {id:4,name:'qqq'},
 //   {id:2,name:'qqq'},

四个操作方法:

add(value):添加某个值,返回Set结构本身。
delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
has(value):返回一个布尔值,表示该值是否为Set的成员。
clear():清除所有成员,没有返回值

let s = new Set();
s.add(1).add(2).add(2);
// 注意2被加入了两次
s.size // 2
s.has(1) // true
s.has(2) // true
s.has(3) // false
 
console.log(s.delete(2));//true
s.has(2) // false

set内部的元素可以遍历for...of...

let set = new Set(['red', 'green', 'blue']);
for (let x of set) {
 console.log(x);
}
// red
// green
// blue

set = new Set([1, 4, 9]);
set.forEach((value, key) => console.log(key + ' : ' + value))
// 1 : 1
// 4 : 4
// 9 : 9


Set 结构的实例有四个遍历方法,可以用于遍历成员。

keys():返回键名的遍历器
values():返回键值的遍历器
entries():返回键值对的遍历器
forEach():使用回调函数遍历每个成员
需要特别指出的是,Set的遍历顺序就是插入顺序。这个特性有时非常有用,比如使用 Set 保存一个回调函数列表,调用时就能保证按照添加顺序调用。

Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。

var m = new Map();
var o = {p: "Hello World"};
 
m.set(o, "content")
m.get(o) // "content"
 
m.has(o) // true
m.delete(o) // true
m.has(o) // false

注意,只有对同一个对象的引用,Map结构才将其视为同一个键。这一点要非常小心。

var map = new Map();
map.set(['a'], 555);
map.get(['a']) // undefined
//set和get方法,表面是针对同一个键,但实际上这是两个值,内存地址是不一样的,因此get方法无法读取该键,返回undefined。

注:如果Map的键是一个简单类型的值(数字、字符串、布尔值),则只要两个值严格相等,Map将其视为一个键,包括0和-0。另外,虽然NaN不严格相等于自身,但Map将其视为同一个键。

实例属性和方法:size、set、get、has、delete、clear
遍历方法:keys()、values()、entries()、forEach()

const map = new Map([
 ['F', 'no'],
 ['T', 'yes'],
]);
 
for (let key of map.keys()) {
 console.log(key);
}
// "F"
// "T"
 
for (let value of map.values()) {
 console.log(value);
}
// "no"
// "yes"
 
for (let item of map.entries()) {
 console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"
 
// 或者
for (let [key, value] of map.entries()) {
 console.log(key, value);
}
// "F" "no"
// "T" "yes"
 
// 等同于使用map.entries()
for (let [key, value] of map) {
 console.log(key, value);
}
// "F" "no"
// "T" "yes"

Maps 和 Objects的区别:

一个 Object 的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值。
Map 中的键值是有序的(FIFO 原则),而添加到对象中的键则不是。
Map 的键值对个数可以从 size 属性获取,而 Object 的键值对个数只能手动计算。
Object 都有自己的原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。

Map 的迭代:
1.for...of

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
 
// 将会显示两个 log。 一个是 "0 = zero" 另一个是 "1 = one"
for (var [key, value] of myMap) {
  console.log(key + " = " + value);
}
for (var [key, value] of myMap.entries()) {
  console.log(key + " = " + value);
}
/* 这个 entries 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的 [key, value] 数组。 */
 
// 将会显示两个log。 一个是 "0" 另一个是 "1"
for (var key of myMap.keys()) {
  console.log(key);
}
/* 这个 keys 方法返回一个新的 Iterator 对象, 它按插入顺序包含了 Map 对象中每个元素的键。 */
 
// 将会显示两个log。 一个是 "zero" 另一个是 "one"
for (var value of myMap.values()) {
  console.log(value);
}
/* 这个 values 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的值。 */

2.forEach()

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
 
// 将会显示两个 logs。 一个是 "0 = zero" 另一个是 "1 = one"
myMap.forEach(function(value, key) {
  console.log(key + " = " + value);
}, myMap)

const map0 = new Map()
 .set(1, 'a')
 .set(2, 'b')
 .set(3, 'c');
 
const map1 = new Map(
 [...map0].filter(([k, v]) => k < 3)
);
// 产生 Map 结构 {1 => 'a', 2 => 'b'}
 
const map2 = new Map(
 [...map0].map(([k, v]) => [k * 2, '_' + v])
  );
// 产生 Map 结构 {2 => '_a', 4 => '_b', 6 => '_c'}

相互转换
Array.from()或者扩展运算符...

const arr = [[{'a': 1}, 111], ['b': 222]]
const myMap = new Map(arr)
[...myMap]//Array.from(myMap)
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]);

set(key, val): 向Map中添加新元素
get(key): 通过键值查找特定的数值并返回
has(key): 判断Map对象中是否有Key所对应的值,有返回true,否则返回false
delete(key): 通过键值从Map中移除对应的数据
clear(): 将这个Map中的所有元素删除
Map的使用.png
Map.png

Set
Set对象允许你存储任何类型的值,无论是原始值或者是对象引用。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set 本身是一个构造函数,用来生成Set 数据结构。Set函数可以接受一个数组(或者具有iterable接口的其他数据结构)作为参数,用来初始化。

+0 与 -0 在存储判断唯一性的时候是恒等的,所以不重复
undefined 与 undefined 是恒等的,所以不重复
NaN 与 NaN 是不恒等的,但是在 Set 中认为NaN与NaN相等,所有只能存在一个,不重复。

// Array 转 Set
var mySet = new Set(["value1", "value2", "value3"]);
// 用...操作符,将 Set 转 Array
var myArray = [...mySet];


add(value):添加某个值,返回 Set 结构本身(可以链式调用)。
delete(value):删除某个值,删除成功返回true,否则返回false。
has(value):返回一个布尔值,表示该值是否为Set的成员。
clear():清除所有成员,没有返回值。


Set 对象作用
数组去重
var mySet = new Set([1, 2, 3, 4, 4]);
[...mySet]; // [1, 2, 3, 4]
并集
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var union = new Set([...a, ...b]); // {1, 2, 3, 4}
交集
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var intersect = new Set([...a].filter(x => b.has(x))); // {2, 3}
差集
var a = new Set([1, 2, 3]);
var b = new Set([4, 3, 2]);
var difference = new Set([...a].filter(x => !b.has(x))); // {1}
set是一种关联式容器,其特性如下:

set以RBTree作为底层容器
所得元素的只有key没有value,value就是key
不允许出现键值重复
所有的元素都会被自动排序
不能通过迭代器来改变set的值,因为set的值就是键
map和set一样是关联式容器,它们的底层容器都是红黑树,区别就在于map的值不作为键,键和值是分开的。它的特性如下:

map以RBTree作为底层容器
所有元素都是键+值存在
不允许键重复
所有元素是通过键进行自动排序的
map的键是不能修改的,但是其键对应的值是可以修改的

参考https://www.runoob.com/w3cnote/es6-map-set.html

相关文章

网友评论

      本文标题:ES6中的Map和Set

      本文链接:https://www.haomeiwen.com/subject/brxufltx.html