认识Set和Map(常用完整版)

作为ES6新增的数据结构,在平时的业务中我倒是没怎么使用过,但是在刷算法题中,Set和Map倒是经常登场。Set作为哈希表,Map作为对象plus,下面就来一起学习一下Set和Map的使用吧

实例属性

Set.prototype.size ,和数组的长度一样理解就行,不过是length换成了size

实例方法

Set.prototype.add() ,如果Set中没有该元素,则插入,且每次只能插入一个元素。注意,Set中每个元素只能插入一次,既同一个Set集合中不能存在相同的元素

Set.prototype.clear() : 清除Set集合中所有的元素

Set.prototype.delete() : 移除某个元素,并返回一个布尔值表示是否移除成功

Set.prototype.entries()

返回一个新的迭代器对象,该对象包含 Set 对象中的代表每个元素的 [value, value] 数组 。这与 Map 对象类似,因此 Set 的每个条目的 keyvalue 都相同。

Set.prototype.forEach()

按照值插入的顺序为 Set 对象中的每个值调用一次 callbackFn。如果提供了 thisArg 参数,它将被用作每次调用 callbackFn 时的 this 值。

Set.prototype.has() :返回一个布尔值,表示Set中是否存在该元素

Set.prototype.keys()和Set.protrtypr.values()返回是一个东西,即键值相同

除了forEach,for...of..也可以迭代

javascript 复制代码
const mySet = new Set(['a','b','c','d'])
for (const [key,value] of mySet.entries()) {
    console.log(`The key ${key} and the value ${value} is the same!`)
}
// The key a and the value a is the same!
// The key b and the value b is the same!
// The key c and the value c is the same!
// The key d and the value d is the same!

Set和Array的相互转换

csharp 复制代码
let set = new Set([1,2,3,4])   //数组转Set 
console.log(set)				//{1,2,3,4}
let arr = [...set]              //Set转数组法2
let arr2 = Array.from(set)      //Set转数组法1
console.log(arr)				//[1,2,3,4]
console.log(arr2)				//[1,2,3,4]
javascript 复制代码
let set = new Set([1,2,3,4])  
// 求数组[2,3,4]和Set{1,2,3,4}的交集
const intersection = new Set([2,3,4].filter((item)=>set.has(item)))
console.log(intersection)        //{2,3,4}
// 求数组[4,5,6]和Set{1,2,3,4}的差集
const difference = new Set([4,5,6].filter((item)=>!set.has(item)))
console.log(difference)         //{5,6}

数组去重

ini 复制代码
// 用于从数组中删除重复元素

const numbers = [2, 3, 4, 4, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 5, 32, 3, 4, 5];

console.log([...new Set(numbers)]);

// [2, 3, 4, 5, 6, 7, 32]

Set与字符串的关系

sql 复制代码
const mySet = new Set('India')
console.log(mySet.size)       //5
// 大小写敏感,且忽略重复项
new Set("Firefox"); // Set(7) { "F", "i", "r", "e", "f", "o", "x" }
new Set("firefox"); // Set(6) { "f", "i", "r", "e", "o", "x" }

这里附上MDN参考网站Set - JavaScript | MDN (mozilla.org)

javascript 复制代码
let obj ={
    'a':1,
    'b':2,
     c:3      //Object的键只能是字符或Symbol,它会自己转
}
const keys= Object.keys(obj)
console.log(keys)
const values= Object.values(obj)
console.log(values)
const arrs = Object.entries(obj)
console.table(arrs)

Map有个神奇的地方就是它可以复制,给我的感觉是和Object.assign一样,而且两者都是浅复制(拷贝),而Set是没有类似方法的

ini 复制代码
const obj= {
    a:0,
    b:{c:1}
}
const target = {}
const obj2 = Object.assign(target,obj)
obj2.b.c = 0		//因为是浅拷贝,对.b的值同一个引用,所以obj.b.c也会变
console.log(obj2)    //{a:0,b:{c:0}}  
console.log(obj)    //{a:0,b:{c:0}}  
console.log(target===obj2)  //true

这里提供一个深拷贝的方法

ini 复制代码
const obj3 = { a: 0, b: { c: 0 } };
const obj4 = JSON.parse(JSON.stringify(obj3));
obj3.a = 4;
obj3.b.c = 4;
console.log(obj4); // { a: 0, b: { c: 0 } }
javascript 复制代码
const myMap= new Map([['a','字母']])
console.log(myMap)
const myMap2 = new Map(myMap)
console.log(myMap2)
console.log(myMap===myMap2)		//false

实例属性

这些属性在 Map.prototype 上定义,并由所有 Map 实例共享。

Map.prototype.size

返回 Map 对象中的键值对数量。

实例方法

Map.prototype.clear()

移除 Map 对象中所有的键值对。

Map.prototype.delete()

移除 Map 对象中指定的键值对,如果键值对存在并成功被移除,返回 true,否则返回 false。调用 delete 后再调用 map.has(key) 将返回 false

Map.prototype.forEach()

以插入顺序为 Map 对象中的每个键值对调用一次 callbackFn。如果为 forEach 提供了 thisArg 参数,则它将作为每一次 callback 的 this 值。

Map.prototype.set()

Map 对象中设置与指定的键 key 关联的值,并返回 Map 对象。

Map.prototype.get()

返回与指定的键 key 关联的值,若不存在关联的值,则返回 undefined

Map.prototype.has()

返回一个布尔值,用来表明 Map 对象中是否存在与指定的键 key 关联的值。

Map.prototype.keys()

返回一个新的迭代器对象,其包含 Map 对象中所有元素的键,以插入顺序排列。

Map.prototype.values()

返回一个新的迭代对象,其中包含 Map 对象中所有的值,并以插入 Map 对象的顺序排列。

Map.prototype.entries()

返回一个新的迭代器对象,其包含 Map 对象中所有键值对 [key, value] 二元数组,以插入顺序排列。

使用 for...of 迭代 Map

Map 可以使用 for...of 循环来实现迭代:

javascript 复制代码
const myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");

for (const [key, value] of myMap) {
  console.log(`${key} = ${value}`);
}
// 0 = zero
// 1 = one

for (const key of myMap.keys()) {
  console.log(key);
}
// 0
// 1

for (const value of myMap.values()) {
  console.log(value);
}
// zero
// one

for (const [key, value] of myMap.entries()) {
  console.log(`${key} = ${value}`);
}
// 0 = zero
// 1 = one

使用 forEach() 迭代 Map

Map 也可以通过 forEach() 方法迭代:

javascript 复制代码
myMap.forEach((value, key) => {
  console.log(`${key} = ${value}`);
});
// 0 = zero
// 1 = one

这里附赠个数组去重的的

数组里全是原始类型,直接用Set,但如果是引用类型那Set就失效了,这里看了某博主分享的后,自己也手写了一遍,注释比较全,嘿嘿!

javascript 复制代码
        function uniqueArr(arr) {
            const res = []
            for (let iterator of arr) {
                let sameFlag = false
                for (let item of res) {
                    if (equl(iterator, item)) {     //有相等就退出
                        sameFlag = true
                        break
                    }
                }
                if (!sameFlag) res.push(iterator)
            }
            return res
        }
        function equl(obj1, obj2) {
            if ((typeof obj1 === 'object' && obj1 !== null) && (typeof obj2 === 'object' && obj2 !== null)) {
                // 都是非null的对象
                if (Object.keys(obj1).length !== Object.keys(obj2).length) return false
                for (const key in obj1) {
                    if (obj2.hasOwnProperty(key)) {
                        if (!equl(obj1[key], obj2[key])) {
                            // 属性值不相同,返回false
                            return false;
                        }
                    } else {
                        // 没有相同的key,直接返回false
                        return false;
                    }
                }
                // 能到这,就是属性数量、属性名、属性值都相同,那就可以判定这两个对象相同
                return true;
            } else {
                // 原始类型作比较,最后的出口
                return obj1 === obj2
            }
        }
        let arr = [1, 1, '2', 3, 1, 2,
            { name: '张三', id: { n: 1 } },
            { name: '张三', id: { n: 1 } },
            { name: '张三', id: { n: 2 } }
        ]
        console.log(uniqueArr(arr))
相关推荐
余生H9 分钟前
前端的全栈混合之路Meteor篇:关于前后端分离及与各框架的对比
前端·javascript·node.js·全栈
程序员-珍12 分钟前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发
axihaihai16 分钟前
网站开发的发展(后端路由/前后端分离/前端路由)
前端
流烟默28 分钟前
Vue中watch监听属性的一些应用总结
前端·javascript·vue.js·watch
自由的dream32 分钟前
0-1背包问题
算法
2401_8572979138 分钟前
招联金融2025校招内推
java·前端·算法·金融·求职招聘
茶卡盐佑星_1 小时前
meta标签作用/SEO优化
前端·javascript·html
Ink1 小时前
从底层看 path.resolve 实现
前端·node.js
金灰1 小时前
HTML5--裸体回顾
java·开发语言·前端·javascript·html·html5
茶卡盐佑星_1 小时前
说说你对es6中promise的理解?
前端·ecmascript·es6