重温JavaScript(lesson20):map和set

上一次我们一起重温了JS中数组相关的内容,这一次我们要来学习ES6新引入的两个数据结构:map和set。map和对象比较像,可以用键来获取值,set则和数组比较像,但是不允许出现重复的值。下面我们就进入详细地学习吧:

1.map

1.1 map和对象的比较

在mao没有诞生以前,要把键和值映射起来的时候,一般都会首选对象。对象能把字符串类型的键映射到任意类型的值。但是这样使用起来还是存在着问题:

1.对象有原型,对象原型中可能存在并不需要的映射;原型上的键名可能和你设置的键名冲突。

2.一个对象的键是无序的,对象不能保证自身属性的顺序。

3.对象中键的个数只能手动计算,所以弄清楚对象中有多少映射比较麻烦。

4.对象的键只能是字符串,这样一来就不能将对象映射到值。

map则解决了这些问题,它是将键和值映射起来的最佳选择,这是因为:

1.map默认情况不包含任何键,只包含显式插入的键。

2.map中的键是有序的。因此,当迭代的时候,一个 Map 对象以插入的顺序返回键值。

3.map 的键值对个数可以轻易地通过size 属性获取。

4.map的键可以是任意值,包括函数、对象或任意基本类型。

下面通过实例看一下map的使用:

1.2 map的使用

1.2.1 设置值与取值

可以使用set()方法为map添加键值对,使用get()方法读取相应键所对应的值,使用size属性返回map中元素的个数:

let map = new Map()
let keyObj = {}
let keyFunc = function() {}
let keyString = 'string'
map.set(keyObj,'keyObjValue')
map.set(keyFunc,'keyFuncValue')
map.set(keyString,'keyStringValue')
console.log(map.size)
//3
console.log(map.get(keyObj))
//keyObjValue
console.log(map.get(keyFunc))
// keyFuncValue
console.log(map.get(keyString))
// keyStringValue

通过上例我们可以看到对象、函数、字符串都可以作为map的键。

可以链式地调用set()方法;当用一个map不存在的key调用get()方法时,就会返回一个undefined;如果key在ma p中已经存在,那么调用set()后key对应的value就会被替换:

map.set('key1','value1')
    .set('key2','value2')
    .set('key3','value3')
console.log(map.size)
// 6

console.log(map.get('key4'))
// undefined

map.set('key3','value33')
console.log(map.get('key3'))
// value33

1.2.2 迭代

使用keys()方法可以拿到map中所有的键;values()可以拿到所有的值;entries()可以以数组的方式获取键值对,数组的第一个元素为键,第二个元素为值;:

console.log(map.keys())
console.log(map.values())
console.log(map.entries())

运行结果如下图所示:

图片

图片

图片

可以使用for…of循环来迭代:

for(let key of map.keys()) {
    console.log(key)
}

运行结果如下图:

图片

for(let value of map.values()) {
    console.log(value)
}

运行结果如下图:

图片

也可以使用forEach()方法来循环迭代:

for(let [key,value] of map) {
    console.log(key,value)
}
map.forEach((value,key) => {
    console.log(value,key)
})

图片

1.2.3 删除和清除

可以使用delete方法删除map中的数据,可以使用clear()方法清除map中的数据:

map.delete('key3')
console.log(map.get('key3'))
// undefined
console.log(map.size)
// 5
map.clear()
console.log(map.size)
// 0

1.2.4 map和数组的转换

可以使用Map构造函数传入由键值对数组组成的数组(二维数组)构造map。而使用Array.from可以将map转换为数组,或者使用展开运算符…

//从数组构造map
let arr = [['key1','value1'],['key2','value2']]
let arrMap = new Map(arr)
console.log(arrMap.get('key1')) 
// value1

//从map构造数组
let arr2 = Array.from(arrMap)
console.log(arr2)
let arr3 = [...arrMap]
console.log(arr3)

1.2.5 map的克隆和合并

可以将一个map传入Map构造函数从而创建另外一个map,即实现复制功能,但是这种复制是只复制数据的浅复制:

// 复制map
let mapOne = new Map([[1,'one']])
let clone = new Map(mapOne)
console.log(clone.get(1))
// one
console.log(clone === mapOne)
// false

可以将多个map合并,合并的方法是在一个数组中将多个map展开,然后这个数组作为参数传给Map构造函数:

// map的合并
let mapTwo = new Map([[1,'1'],[2,'two']])
let merged = new Map([...mapOne,...mapTwo])
console.log(merged)
//  Map对象同数组进行合并时,如果有重复的键值,则后面的会覆盖前面的

图片

2.set

set是一个不允许重复的数据的集合,允许你存储任何类型的唯一值,无论是原始类型还是引用类型。

2.1 添加元素

我们看一下使用set的例子:

let set = new Set();

set.add(1);
set.add(2);
console.log(set);
//Set(2) {1, 2}
set.add(2);
console.log(set)
//Set(2) {1, 2}
set.add('new');
set.add({name: 'name'});
console.log(set)
// Set(4) {1, 2, "new", {…}}
console.log(set.size);
//4

如上代码使用Set的构造方法新建了一个set:new Set();然后向set中添加了2个不同的元素1和2;接着又向set中添加元素2时,由于set中已经存在2,所以添加失败;接着向set中添加字符串和对象;使用size属性可以查看当前size的元素个数。

2.2 删除元素

可以使用delete方法删除set中的元素,如果删除成功则返回true;如果删除一个set中不存在的元素将返回false;可以使用has方法判断元素是否在set中。

let res =  set.delete(2)
console.log(res)
// true
console.log(set.has(2))
//false
res = set.delete(2)
console.log(res)
//false

2.3 迭代

可以使用for… of迭代set中的元素;set的键和值是相等,所以set.keys() ,set.values()得到的结果是一样的,set.entries() 得到的每个元素都是一个数组,其中是两个一样的元素。看一下代码:

for(let item of set) {
    console.log(item)
    //1
    //new
    //{name: "name"}
}

for(let item of set.keys()) {
    console.log(item)
    //1
    //new
    //{name: "name"}
}

for(let item of set.values()) {
    console.log(item)
    //1
    //new
    //{name: "name"}
}

for(let item of set.entries()) {
    console.log(item)
    // [1, 1]
    // ["new", "new"]
    // [{name: "name"},{name: "name"}]
}

2.4 和数组的转换

使用Array.from方法可以把Set转换为数组;在调用Set构造方法时可以传入一个数组就可以得到Set。如下代码所示:

let arr =  Array.from(set);
console.log(arr);
// [1, "new",{name: "name"}]

set = new Set([1,2,3,3,4])
console.log(set)
//  {1, 2, 3, 4}

另外也可以通过…运算符的方法,将Set转换为数组:

arr = [...set]
console.log(arr)
// [1, 2, 3, 4]

2.5 Set的集合运算

首次看一下求交集的例子:

let set1 = new Set([1,2,3]);
let set2 = new Set([2,3,4]);
// 求交集
function intersection(set1, set2) {
    return new Set([...set1].filter(x => set2.has(x)))
}
let resSet = intersection(set1,set2);
console.log(resSet);
// Set(2) {2, 3}

再看一下求差集的例子:

let set1 = new Set([1,2,3]);
let set2 = new Set([2,3,4]);
function difference(set1, set2) {
   return  new Set([...set1].filter(x => !set2.has(x)));
}
resSet = difference(set1,set2);
console.log(resSet);
// Set(1) {1}

当然你也可以使用如下的方法求Set集合的差集:

function difference(setA, setB) {
    let _difference = new Set(setA);
    for (let elem of setB) {
        _difference.delete(elem);
    }
    return _difference;
}

再看一下是否是子集的例子:

function isSuperset(set, subset) {
    for (let elem of subset) {
        if (!set.has(elem)) {
            return false;
        }
    }
    return true;
}

set1  = new Set([1,2,3])
set2  = new Set([2,3])
console.log(isSuperset(set1,set2));
//true

再看一下求并集的例子:

function union(setA, setB) {
    let _union = new Set(setA);
    for (let elem of setB) {
        _union.add(elem);
    }
    return _union;
}

set1 = new Set([1,2,3])
set2 = new Set([3,4,5])
console.log(union(set1,set2))
// Set(5) {1, 2, 3, 4, 5}

最后看一下求交集的例子:

function intersection(setA, setB) {
    let _intersection = new Set();
    for (let elem of setB) {
        if (setA.has(elem)) {
            _intersection.add(elem);
        }
    }
    return _intersection;
}
set1 = new Set([1,2,3])
set2 = new Set([3,4,5])
console.log(intersection(set1,set2))
// Set(1) {3}

以上就是今天我们重温JS全部的内容,我们以一张导图来回顾一下今天的内容:

图片

我们这次的分享就到这里,下次再会。如有错误,请不吝指正。温故而知新,欢迎和我一起重温旧知识,攀登新台阶~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

重温新知

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值