JavaScript——Set和Map基础用法

Set

ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

基本用法

  • Set.prototype.size:返回Set实例的成员总数。
  • Set.prototype.add(value):添加某个值,返回 Set 结构本身。
  • Set.prototype.delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
  • Set.prototype.has(value):返回一个布尔值,表示该值是否为Set的成员。
  • Set.prototype.clear():清除所有成员,没有返回值。
const setNum = new Set([1, 2, 3, 1]);  // SetNum构造函数初始化

console.log(setNum.size);// 3
setNum.add(4);  //向集合中添加不存在的元素
console.log(setNum.has(2));//true

for (const item of setNum) {
    console.log(item);
}
// 1 2 3 4

setNum.delete(2);//删除集合中的某个元素
console.log(setNum.has(2));//false 

setNum.clear();//清空集合
console.log(setNum.size);//0

使用内置构造函数创建Set。如果不传入任何参数,将创建一个空的Set。上例中由于Set成员的值都是唯一的,最后setNum中只会存在一个2。如果add(添加)一个2,是没有效果的。

遍历方法

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

  • Set.prototype.keys():返回键名的遍历器。
  • Set.prototype.values():返回键值的遍历器。
  • Set.prototype.entries():返回键值对的遍历器。
  • Set.prototype.forEach():使用回调函数遍历每个成员。
const 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.forEach((value, key) => {
    console.log(key, value);
});
//  red,red  green,green  blue,blue 

上面代码中,entries方法返回返回的遍历器,也就是数组。同时包括键名和键值,每次输出的数组,它的两个成员都相同。forEach方法的参数就是接收一个回调函数。依次是键名、键值、集合本身(本例中省略了该参数)。还有第二个参数,表示绑定回调函数内部的this

遍历应用

去重数组和字符串.

// 去除数组的重复成员
const arr = [3, 5, 2, 2, 5, 5];
const unique = [...new Set(arr)];// [3, 5, 2]

//也可以去除字符串里面的重复字符
const str =[...new Set('ababbc')].join('');// "abc"

结合扩展运算符...实现两个集合的并集、交集、差集。

const a = new Set([1, 2, 3]);
const b = new Set([4, 3, 2]);

// 并集
const union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}

// 交集
const intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}

// (a 相对于 b 的)差集
const difference = new Set([...a].filter(x => !b.has(x)));
// Set {1}

WeakSet

WeakSet结构与Set类似,也是不重复的值的集合,但是与Set有两个区别。首先,WeakSet的成员只能是对象,而不能是其他类型的值。

const ws = new WeakSet();
ws.add({});

ws.add(1);// TypeError: Invalid value used in weak set

其次,WeakSet中的对象都是弱引用,即垃圾回收机制不考虑WeakSet对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于WeakSet之中。

WeakSet结构有以下三个方法:

  • WeakSet.prototype.add(value):向WeakSet实例添加一个新成员。返回 WeakSet结构本身
  • WeakSet.prototype.delete(value):清除WeakSet实例的指定成员。返回一个布尔值,表示删除是否成功。
  • WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在WeakSet实例之中。
const obj = { name: 'jake' }
const ws = new WeakSet();
ws.add(obj);

console.log(ws.has(obj));//true

console.log(ws.delete(obj));//true

console.log(ws.has(obj));//false

WeakSet没有size属性,没有办法遍历它的成员。因为成员都是弱引用,随时可能消失,遍历机制无法保证成员的存在,很可能在遍历结束,成员就取不到了。

Map

JavaScript 的对象,本质上是键值对的集合,但是传统上只能用字符串当作键。

<div id="firstElement"></div>
<div id="secondElement"></div>
<script>
    const firstElement = document.getElementById("firstElement");
    const secondElement = document.getElementById("secondElement");// 创建两个HTML元素
    const map = {};//定义空对象,使用映射存储HTML节点的额外信息
    map[firstElement] = { data: "firstElement" };
    console.log(map[firstElement].data === "firstElement");//true

    map[secondElement] = { data: "secondElement" };
    console.log(map[firstElement].data === "firstElement");//false
    console.log(map[secondElement].data === "secondElement");//true
</script>

当我们第一次访问map[firstElement].data时结果是firstElement,然后给map对象第二次添加数据。在访问map[firstElement].data发现值变成了secondElement。因为对象的key必须是字符串,当用HTML元素作为key时,其值被tostring方法静默装换成为了字符串类型(“[object HTMLDivElement]”)。 覆盖了第一个元素的值。

Map基本用法

  • Map.prototype.size:返回Map实例的成员总数。
  • Map.prototype.set(key,value)set方法设置键名key对应键值为value,返回整个Map结构,如果key已经有值,则键值会被更新,否则就新生成该键。
  • Map.prototype.get(key):get方法读取key对应的键值,如果找不到key,返回undefined
  • Map.prototype.delete(key):删除某个值,返回一个布尔值,表示删除是否成功。
  • Map.prototype.has(key):返回一个布尔值,表示该值是否为Map的成员。
  • Map.prototype.clear():清除所有成员,没有返回值。
const map = new Map(); // 使用Map构造函数创建map
const ninja1 = { name: "Jake" };
const ninja2 = { name: "David" };
const ninja3 = { name: "Helen" }; // 定义3个ninja对象
map.set(ninja1, { age: 20 });//使用Map的set方法,建立两个ninja对象的映射关系
map.set(ninja2, { age: 30 });

// 使用Map的get方法获取ninja对象
console.log(map.get(ninja1).age === 20); //true
console.log(map.get(ninja2).age === 30); //true
// 验证第三个ninja对象不存在映射关系
console.log(map.get(ninja3) === undefined); //true

// 验证map中只存在前两个对象的映射
console.log(map.size === 2);//true

//使用has方法一验证map中是否存在指定的key
console.log(map.has(ninja1) === true && map.has(ninja2) === true);// true

//使用delete方法从map中删除key
map.delete(ninja1);
console.log(map.has(ninja1) === false && map.size === 1);//true

//使用clear方法完全清空map
map.clear();
console.log(map.size === 0);//true

遍历方法

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

  • Map.prototype.keys():返回键名的遍历器。
  • Map.prototype.values():返回键值的遍历器。
  • Map.prototype.entries():返回键值对的遍历器。
  • Map.prototype.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"

map.forEach((value, key) => {
    console.log(key, value);
}); 
// "F" "no"   "T" "yes"

Map应用

Map和数组转换

//Map转为数组
const myMap1 = new Map()
  .set('Jake', 20)
  .set({foo: 3}, ['abc']);
console.log([...myMap1]);// [['Jake', 20], [{foo: 3}, ['abc']]]

//数组转为Map
const myMap2 =new Map([
    ['Jake', 20], 
    [{foo: 3}, ['abc']]
]);
console.log(myMap2);
// Map {
//   "Jake" => 20,
//   Object {foo: 3} => ['abc']
// }

Map和对象转换

//Map转为对象
//如果map的键都是字符串,可以无损的转换为对象

const myMap1 = new Map([
    ['Jake', 20],
    ['David', 30]
]);

function mapToObj(map) {
    const obj = {};
    map.forEach((value, key) => {
        obj[key] = value;
    })
    return obj;
}
console.log( mapToObj(myMap1));

//对象转换Map
const obj = {"a":1, "b":2};
const myMap2 = new Map(Object.entries(obj));

WeakMap

WeakMap结构与Map结构类似,也是用于生成键值对的集合。首先,WeakMap只接受对象作为键名,不接受其他类型的值作为键名。

const wm = new WeakMap();
wm.set({},1);

wm.set(1,1);//Invalid value used as weak map key

其次,WeakMap的键名所指向的对象,不计入垃圾回收机制。键值依然是正常使用。

const wm = new WeakMap();
let key1 = {};
let obj1 = {foo: 1};
let key2 = {foo: 1};
let obj2 = {};

wm.set(key1, obj1);
wm.set(key2, obj2);

obj1 = null;
key2 = null;

wm.get(key1);// {foo: 1}
wm.get(key2);// undefined

WeakMap的语法:

  • WeakMap.prototype.set(key,value)set方法设置键名key对应键值为value,返回整个Map结构,如果key已经有值,则键值会被更新,否则就新生成该键。

  • WeakMap.prototype.get(key):get方法读取key对应的键值,如果找不到key,返回undefined

  • WeakMap.prototype.delete(key):删除某个值,返回一个布尔值,表示删除是否成功。

  • WeakMap.prototype.has(key):返回一个布尔值,表示某个值是否在WeakSet实例之中。

  • WeakMap.prototype.delele(key):返回一个布尔值,表示某个值是否在WeakMap实例之中。

<div id="foo"></div>
<div id="fn"></div>
<script>
    const wm = new WeakMap();
    const foo  = document.querySelector('#foo');
    const fn  = document.querySelector('#fn');

    wm.set(foo,1);
    wm.set(fn,2);

    console.log(wm.get(foo));// 1

    console.log(wm.delete(foo));// true

    console.log(wm.has(foo));// false
    console.log(wm.has(fn));// true
</script>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值