ES6一Set 、Map数据结构

Set、Map是ES6中新增的两种集合类型,用于在不同的场景中发挥作用

1.Set

Set本身是个构造函数,用来生成Set数据结构,它类似于数组,但是没有随机访问的能力,最重要的是,Set 中的元素具有唯一性,不允许存储相同的元素Set 内部判断两个值是否不同,使用的算法类似于精确相等运算符(===),可用于数组去重操作。

1.1 创建set集合

//创建一个没有任何内容的set集合
new Set()  //Set(0) {size: 0}

//创建一个具有初试内容的set集合,内容来自于可迭代对象每一次迭代的结果
new Set([1,3,2,3])//结果直接去重:Set(3) {1, 3, 2}

//由元素唯一性这个特点,可以利用在数组去重上
//方法一:Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组
Array.from(new Set([1,3,2,3])) //[1, 3, 2]

//方法二:拓展运算符
[...new Set(arr)] [1, 3, 2]

1.2 Set 的属性和实例方法

(1) size属性
const s = new Set();
console.log(s.size);//0,返回Set结构的成员总数
(2)操作方法
  • add(value):添加某个值,返回Set结构本身
    注意:向 Set 加入值的时候,不会发生类型转换,所以1和"1"是两个不同的值
  • delete(value):删除某个值,返回一个布尔值,表示删除是否成功
  • has(value):返回一个布尔值,表示该值是否为Set的成员

clear():清除所有成员,没有返回值

const s= new Set(); //初始化: Set(0) {size: 0}

s.add(0).add("1").add('a').add([1,2]); //添加成员: Set(4) {0, '1', 'a', Array(2)}

s.delete(3)  //false, 成员中无 3, 删除失败: Set(4) {0, '1', 'a', Array(3)}

s.has(0) //true, 成员中有 0,返回true  

s.clear()//清除所有成员,没有返回值: Set(0) {size: 0}
(3)遍历方法
Set的遍历顺序就是插入顺序。这个特性有时非常有用,比如使用 Set 保存一个回调函数列表,调用时就能保证按照添加顺序调用。
  • Set.prototype.keys():返回键名的遍历器
  • Set.prototype.values():返回键值的遍历器
  • Set.prototype.entries():返回键值对的遍历器
  • Set.prototype.forEach():使用回调函数遍历每个成员

keys方法、values方法、entries方法返回的都是遍历器对象。由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。此外,Set 结构的实例默认可遍历,它的默认遍历器生成函数就是它的values方法,可以省略values方法,直接用for...of循环遍历 Set。。

let set = new Set([1, 2, 3]);

for (let i of set.keys()) {
  console.log(i);
}
// 1  2  3

for (let i of set.values()) {
  console.log(i);
}
// 1  2  3

for (let i of set) {
   console.log(i)
}
//1  2  3

for (let i of set.entries()) {
  console.log(i);
}
// [1, 1]  [2, 2]  [3, 3] 

set.forEach(i => {
  console.log(i)
})
// 1  2  3

2.Map

Map 是 ES6 中新增的数据结构,Map 类似于对象,Object 结构提供了“字符串—值”的对应,但普通对象的 key 必须是字符串或是数字,而Map 结构提供了“值—值”的对应,而Map 的 key 可以是任何数据类型,是一种更完善的 Hash 结构实现。Map 的用法和普通对象基本一致,如果你需要“键值对”的数据结构,Map 比 Object 更合适

2.1 创建Map实例

const m = new Map(); //创建一个空映射:Map(0) {size: 0}

//接受可迭代对象作为参数用来初始化,需要包含键/值对数组。可迭代对象中的每个键/值对都会按照迭代顺序插入到新映射实例中(类似于二维数组) 
const m = new Map([
	[1, 'a'],
	[2, 'b'],
	[3, 'c']
]); //Map(3) Map(3) {1 => 'a', 2 => 'b', 3 => 'c'}

Array.from(m); // [[1, 'a],[2, 'b],[3, 'c]]

2.2 Map实例的属性和操作方法

(1) size属性
const m = new Map([
	[1, 'a'],
	[2, 'b'],
	[3, 'c']
]);
map.size // 返回 Map 结构的成员总数: 3
(2)操作方法
  • Map.prototype.set(key, value):Map设置某个值,返回当前的Map对象,因此可以采用链式写法。
  • Map.prototype.get(key):读取key对应的键值,如果找不到key,返回undefined
  • Map.prototype.has(key):返回一个布尔值,表示某个键是否在当前 Map 对象之中。
  • Map.prototype.delete(key):删除某个键,返回true。如果删除失败,返回false
  • Map.prototype.clear():清除所有成员,没有返回值
const m = new Map(); 
m.set('a', 1)        // 键是字符串
m.set(2, 'b')     // 键是数值
m.set(undefined, 'c')    // 键是 undefined
m.set({p: 'Hello World'}, 'content')       //  键是 object 
// Map(4) {'a' => 1, 2 => 'b', undefined => 'c', {…} => 'content'}

m.get('a') // 1
m.get(1) // 无键为1的成员对象,返回 undefined

m.has('a') // true, 'a' 在Map对象中
m.has(1) // false, 1不在Map对象中

m.delete(2) //true,删除2成功:  Map(3) {'a' => 1, undefined => 'c', {…} => 'content'}
m.delete(1) // false,Map对象中无键1,删除1不成功

m.clear() //清除所有成员,没有返回值: Map(0) {size: 0}

(3)遍历方法

Map 结构原生提供三个遍历器生成函数和一个遍历方法,Map 的遍历顺序就是插入顺序

  • Map.prototype.keys():返回键名的遍历器。
  • Map.prototype.values():返回键值的遍历器。
  • Map.prototype.entries():返回所有成员的遍历器,Map 结构的默认遍历器接口
  • Map.prototype.forEach():遍历 Map 的所有成员,与数组的forEach方法类似。
const m = new Map([
  [1, 'a'],
  [2,  'b'],
]);

for (let key of m.keys()) {
  console.log(key);
}
// 1  2

for (let value of m.values()) {
  console.log(value);
}
// 'a'  'b'

for (let item of m.entries()) {
  console.log(item[0], item[1]);
}
// 1 'a'    2 'b'

// 或者
for (let [key, value] of m.entries()) {
  console.log(key, value);
}
// 1 'a'    2 'b'

// 等同于使用m.entries()
for (let [key, value] of m) {
  console.log(key, value);
}
// 1 'a'    2 'b'

m.forEach((value, key, m) => {
  console.log("Key: %s, Value: %s", key, value);
});
//Key: 1, Value: a     Key: 2, Value: b  

m.forEach(item => {
  console.log(item)
})
// 'a'  'b'

2.3  Map与其他数据结构的互相转换

(1)Map 转为数组
const m = new Map()
  .set(1, 'a')
  .set(2, 'b');

//方法一:Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组
Array.from(m) // [[1,'a'], [2, 'b']]

//方法二:拓展运算符
[...m] // [[1,'a'], [2, 'b']]
(2)数组 转为 Map
//将数组传入 Map 构造函数,就可以转为 Map。
new Map([
  [1,'a'], 
  [2, 'b']
])
// Map {1 => 'a', 2 => 'b'}
(3)Map 转为对象

如果所有 Map 的键都是字符串或者数字,它可以无损地转为对象,如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名

function strMapToObj(map) {
  let obj = Object.create(null); //相当于let obj={}
  for (let [k,v] of strMap) {
    obj[k] = v;
  }
  return obj;
}

const m = new Map()
  .set('a', 1)
  .set(2, 'b')
  .set([1,2], 'c');
  
const obj = strMapToObj(m)
console.log(obj)// { 'a': 1, 2: 'b', '1,2': 'c' }
(4)对象转为 Map

对象转为 Map 可以通过Object.entries()(ES6新增方法)。

let obj = {1:'a', 2:'b'};
let map = new Map(Object.entries(obj));

//此外,也可以自己实现一个转换函数。
function objToStrMap(obj) {
  let strMap = new Map();
  for (let k of Object.keys(obj)) {
    strMap.set(k, obj[k]);
  }
  return strMap;
}
objToStrMap({1:'a', 2:'b'})
// Map(2) {'1' => 'a', '2' => 'b'}
(5)Map 转为 JSON
function strMapToJson(map) {
  return JSON.stringify(strMapToObj(map));
}//Map 的键名都是字符串

function mapToArrayJson(map) {
  return JSON.stringify([...map]);
}//Map 的键名有非字符串

let m = new Map().set(1, 'a').set(2, 'b');
strMapToJson(m)
// '{"1":"a","2":"b"}'
(6)JSON 转为 Map
function jsonToStrMap(jsonStr) {
  return objToStrMap(JSON.parse(jsonStr));
} //所有键名都是字符串

jsonToStrMap('{"1": 'a', '2': 'b'}')
// Map {1 => 'a', 2 => 'b'}

function jsonToMap(jsonStr) {
  return new Map(JSON.parse(jsonStr));
} //整个 JSON 就是一个数组,且每个数组成员本身,又是一个有两个成员的数组

let jsonStr1='[[1, 'a'],[2,'b']]';
jsonToMap(jsonStr1)
// Map {1 => 'a', 2 => 'b'}

3.Set 和 Map 的区别

不同点

  • 定义不同:Set类似于数组,但是成员的值都是唯一的,没有重复的值;
    Map类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
  • 操作方法不同:Set:add, has, delete, clear;
                             Map: set, get, has, delete, clear。
  • 遍历方法不同: Set 结构的实例有四个遍历方法keys(), values(), entries(),forEach(),可以用于遍历成员,它的默认遍历器生成函数就是它的values方法;
                            Map 结构原生提供三个遍历器生成函数keys(), values(), entries()和一个遍历方法forEach(),Map 结构的默认遍历器接口是entries方法。

相同点:size属性相同

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值