【JavaScript进阶之旅 ES6篇 第十五章】Set、Map、Set跟Map跟Array跟Object的对比
文章目录
- 一、Set
- 1、基本用法
- 2、Set.prototype
- 二、Map
- 1、基本用法
- a. 键名为对象时
- b. 普遍对象不能实现键值一一对应
- c. Map数据结构实现键为对象的一一对应
- d. 参数
- e. 键名是引用值或原始值的问题
- 2、Map.prototype
- a. 操作Map数据结构的方法
- b. 遍历Map数据结构的方法
- 三、Map与其他数据结构的相互转换
- 1、Map数据结构转换为数组
- 2、数组转换为Map结构
- 3、Map转换为对象
- 4、对象转换为Map
- 四、Map PK Array
- 1、增add
- 2、查search
- 3、改modify
- 4、删delete
- 五、Set PK Array
- 1、增add
- 2、查search
- 3、改modify
- 4、删delete
- 六、Map vs Set vs Object
- 1、增add
- 2、查search
- 3、改modify
- 4、删delete
Set\Map\Promise\Proxy都是ES6新增语法,不可以语法降级
一、Set
1、基本用法
ES6新增的数据结构,成员是唯一的"数组"
● Set数据结构的特征:
a. Set构造函数的参数必须是具备iterator接口的数据解构类型
b. Set构造函数的参数必须唯一的(不可重复)
// 参数是具备iterator接口的数据结构:数组、类数组
const set = new Set([undefined, undefined, null, null, NaN, NaN, 1, true, '1', {}, {}, [], []]);console.log(set); // Set {undefined, null, NaN, 1, true, '1', Object, Object, Array, Array}
2、Set.prototype
注意: Set方法操作是实时性的
a. 操作Set数据结构的方法
- Set.prototype.add
● 添加数据结构,返回是set结构本身
● 可以链式调用const set = new Set();const x = {a: 1},y = {b: 2};set.add(x).add(y);console.log(set); // Set(2) {{…}, {…}}
console.log(set.size); // 2set.delete(x); // 返回值:true
console.log(set);
- Set.prototype.delete
● 删除数据结构,返回boolean值set.delete(x); // 返回值:true
console.log(set); // Set(1) {{…}}
- Set.prototype.clear
● 清空所有的数据结构,返回值是undefinedset.clear();
- Set.prototype.has
● 接收一个值,判断该值是否在set数据结构中,返回值是boolean值set.has(x);
b. 遍历Set结构的方法
- Set.prototype.keys/values/entries
Set 当中没有键名const set = new Set([2, 3, 4, 5]);// Set 当中没有键名
for(let i of set.keys()) {console.log(i); // 2 3 4 5
}for(let i of set.values()) {console.log(i); // 2 3 4 5
}for(let i of set.entries()) {console.log(i); // [2, 2] [3, 3] [4, 4] [5, 5]
}
- for of
● Set.prototype[Symbol.iterator] === Set.prototype.values // true
- forEach
● 跟数组的forEach一样
● 回调函数的参数: a. valueb. keyc. setconst set = new Set([2, 3, 4, 5]);set.forEach((value, keys, set) => {console.log(value); // 2console.log(keys); // 2console.log(set); // Set(4) {2, 3, 4, 5}
});● 数组去重const newArr = [...new Set(arr)];● 将set中的数翻一倍const set = new Set([2, 3, 4, 5]);const newSet = new Set([...set].map(value => value * 2));
console.log(newSet); // Set(4) {4, 6, 8, 10}
c. Set数据结构结合map的使用映射出一个新的结构
● 数组结合map、parseInt使用const arr = [1, 2, 3, 4];
const newArr = arr.map(parseInt);// parseInt有两个参数,以第二个参数为进制数的方式转换第一个参数
// parseInt(1, 0); // 1
// parseInt(2, 1); // NaNconsole.log(newArr); // [1, NaN, NaN, NaN]● Set结合map、parseInt使用const set = new Set([2, 3, 4, 5]);
const set2 = new Set([[...set].map(parseInt)]);console.log(set2); // Set(1) {Array(4)}
// [
// {// "value": [
// 2,
// null,
// null,
// null
// ]
// }
// ]
d. Set数据结构结合filter的使用
const set = new Set([2, 3, 4, 5]);
const set2 = new Set([[...set].filter(item => item % 2 === 0)]);console.log(set2);
// Set(1) {Array(2)}
// [
// 2,
// 4
// ]
e. 交集、并集、差集
let a = new Set([1, 2, 3]);
let b = new Set([2, 3, 4]);// 并集
let union = new Set([...a, ...b]);
console.log(union); // Set(4) {1, 2, 3, 4}// 交集
let intersect = new Set([...a].filter(item => b.has(item)));
console.log(intersect); // Set(2) {2, 3}// 差集
let difference = new Set([...a].filter(item => !b.has(item)));
console.log(difference); // Set(1) {1}
f. Set数据结构结合from的使用映射出一个新的结构
const set = new Set([2, 3, 4, 5]);
const set2 = new Set(Array.from(set, item => item * 2));console.log(set2); // Set(4) {4, 6, 8, 10}
二、Map
1、基本用法
a. 键名为对象时
b. 普遍对象不能实现键值一一对应
var m = {};
var x = {id: 1},y = {id: 2};
m[x] = 'foo'; // -> 不能实现键值一一对应
m[y] = 'bar';
console.log(m); // {[object Object]: 'bar'}
console.log(m[x]); // bar
console.log(m[y]); // bar
c. Map数据结构实现键为对象的一一对应
对象里不可以实现一一对应,所以引用了Map数据结构
- 键值:一一对应
const m = new Map();const x = {id: 1},y = {id: 2};m.set(x, 'foo');
m.set(y, 'bar');console.log(m.get(x)); // foo
console.log(m.get(y)); // barconsole.log(m); // Map(2) {{…} => 'foo', {…} => 'bar'}
d. 参数
- Map的参数是具备iterator接口的数据结构
- 参数是双元数组,key value的形式
const m = new Map([ // 参数是双元数组,key value的形式['name1', 'zhangsan'],['name2', 'lisi']
]);// 键名相同会覆盖
m.set('name3', 'wangwu');
m.set('name4', 'zhaoliu');console.log(m);
/**Map(4) {'name1' => 'zhangsan', 'name2' => 'lisi', 'name3' => 'wangwu', 'name4' => 'zhaoliu'}
[[Entries]]
0: {"name1" => "zhangsan"}
1: {"name2" => "lisi"}
2: {"name3" => "wangwu"}
3: {"name4" => "zhaoliu"}
size: 4
[[Prototype]]: Map*/
- 模拟给参数的过程
const m = new Map();
const items = [['name1', 'zhangsan'],['name2', 'lisi']
];// 通过模式匹配来取值:[key, value]
items.forEach(([key, value]) => m.set(key, value));
console.log(m); // Map(2) {'name1' => 'zhangsan', 'name2' => 'lisi'}
e. 键名是引用值或原始值的问题
const map = new Map();map.set([5], 555);
console.log(map.get([5])); // undefined
const map = new Map();
let arr = [5];map.set(arr, 555);
console.log(map.get(arr)); // 555
- Map中正零跟负零是相等的
map.set(+0, 444);
console.log(map.get(-0)); // 444
注意:
+0 === -0; // true
Object.is(+0, -0); // false
- Map中不存在隐式转换的问题
map.set('true', 1);
map.set(true, 2);console.log(map.get(true)); // 2
- Map中键值为null、undefined、NaN的问题
map.set(undefined, 1);
map.set(null, 2);console.log(map.get(null)); // 2map.set(NaN, 123);
map.set(NaN, 234);
// 在Map中 NaN === NaN的,所以被覆盖
console.log(map.get(NaN)); // 234
- 注意:
NaN === NaN; // false
Object.is(NaN, NaN); // true
2、Map.prototype
a. 操作Map数据结构的方法
Map中的操作方法都是实时的
- Map.prototype.set
- 设置键值
- 返回值是Map实例,所以可以链式调用
- 注意:该方法是实时的
const map = new Map();
console.log(map); // 已经设置值成功map.set('name', 'lyb').set('name2', 'lyw');
- Map.prototype.get
- 获取键对应的值
- 返回值为该值
const map = new Map();map.set('name', 'lyb').set('name2', 'lyw');
console.log(map.get('name2')); // lyw
- Map.prototype.delete
- 删除指定的键值
- 参数为要删除的键
const map = new Map();console.log(map);
map.set('name', 'lyb').set('name2', 'lyw');
console.log(map.get('name2')); // lyw
console.log(map.delete('name')); // true
- Map.prototype.has
- 判断该键是否在Map结构中
- 返回boolean值
const map = new Map();console.log(map);
map.set('name', 'lyb').set('name2', 'lyw');
console.log(map.has('name2')); // true
- Map.prototype.clear
- 清空Map结构中的键值
- 返回值:undefined
const map = new Map();console.log(map);
map.set('name', 'lyb').set('name2', 'lyw');
console.log(map.clear()); // undefined
- Map.prototype.size
- 该方法返回Map数据结构的个数
- 注意:该方法不是实时的
const map = new Map([['name', 'lyb']]);console.log(map.size); // 1map.set('name2', 'lyb');
map.set('name3', 'lyw');
const map = new Map([['name', 'lyb']]);map.set('name2', 'lyb');
map.set('name3', 'lyw');console.log(map.size); // 3
b. 遍历Map数据结构的方法
- Map.prototype.keys/values/entries
const map = new Map();// console.log(Map.prototype);
map.set('name', 'lyb').set('name2', 'lyw');for(let keys of map.keys()) {console.log(keys); // name name2
}for(let values of map.values()) {console.log(values); // lyb lyw
}for(let entries of map.entries()) {console.log(entries); // 'name', 'lyb'] ['name2', 'lyw']
}
- for of
for(let e of map) {console.log(e); // 'name', 'lyb'] ['name2', 'lyw']}
- map[Symbol.iterator] === map.entries
console.log(map[Symbol.iterator] === map.entries ); // true
三、Map与其他数据结构的相互转换
1、Map数据结构转换为数组
- 使用拓展运算符
...
const m = new Map();m.set(true, 2).set({foo: 2}, ['abc']);console.log([...m]);
2、数组转换为Map结构
const m = new Map([[true, 2],[{foo: 2}, ['abc']]
]);console.log(m);
3、Map转换为对象
const m = new Map([[true, 2],[{foo: 2}, ['abc']]
]);function strMapToObj(strMap) {let obj = Object.create(null);// for(let [key, value] of strMap){} 效果一样for(let [key, value] of strMap.entries()) {obj[key] = value;}return obj;
}
4、对象转换为Map
let obj = {true: 1,false: 0
}function objToStrMap(obj) {let m = new Map();for(let key of Object.keys(obj)) {m.set(key, obj[key]);}return m;
}
四、Map PK Array
1、增add
let m = new Map(),a = new Array();m.set('t', 1);
a.push({'t': 1});console.log(m, a);
2、查search
let m = new Map();
let a = new Array();m.set('t', 1);
a.push({'t': 1});console.log(m, a);console.log(m.has('t')); // true
console.log(a.find(val => val.t)); // {t: 1}
3、改modify
let m = new Map();
let a = new Array();m.set('t', 1);
a.push({'t': 1});console.log(m, a);m.set('t', 2);
a.forEach(item => item.t ? item.t = 2: "");console.log(m, a);
4、删delete
let m = new Map();
let a = new Array();m.set('t', 1);
a.push({'t': 1});m.delete('t');// splice:删除|增加数组中的元素,参数:起始项的索引位置(必传)、删除的个数、增加的元素
a.splice(a.findIndex(item => item.t),1
);
五、Set PK Array
1、增add
let set = new Set(),arr = new Array();set.add({t: 1});
arr.push({t: 1});
2、查search
set.has({t: 1}); //false
arr.find(item => item.t); // {t: 1}
3、改modify
set.forEach(item => item.t ? item.t = 2 : '');
arr.forEach(item => item.t ? item.t = 2 : '');
4、删delete
set.forEach(item => item.t ? set.delete(item) : '');
arr.splice(arr.find(item => item.t),1
);
六、Map vs Set vs Object
1、增add
let o = {},m = new Map(),s = new Set();let obj = {t: 1};m.set(obj, 1);
s.add(obj);
o['t'] = 1;console.log(m, s, o);
2、查search
console.log({m_exist: m.has(obj),s_exist: s.has(obj),// 查找属性是否在对象里的两种方法o_exist: 't' in o,o_exist: o.hasOwnProperty('t')
}); // {m_exist: true, s_exist: true, o_exist: true}
3、改modify
m.set(obj, 2);
obj.t = 2;
o.t = 2;
4、删delete
m.delete(obj);
s.delete(obj);
delete o['t'];
总结: Map、Set从语法上面都有相应的iterator迭代器接口,底层优化上相对于Object、Array是更好的,从操作角度来说Map、Set比Array、Object操作更加优雅。优先使用Map、Set。
【JavaScript进阶之旅 ES6篇 第十五章】Set、Map、Set跟Map跟Array跟Object的对比相关推荐
- 鸟哥的Linux私房菜(基础篇)- 第十五章、磁碟配额(Quota)与进阶文件系统管理
第十五章.磁碟配额(Quota)与进阶文件系统管理 最近升级日期:2009/09/10 如果您的 Linux 服务器有多个用户经常存取数据时,为了维护所有使用者在硬盘容量的公平使用,磁碟配额 (Quo ...
- 鸟哥的Linux私房菜(基础篇)- 第二十五章、 Linux 备份策略
第二十五章. Linux备份策略 最近升级日期:2009/09/18 万一不幸你的 Linux 被黑客入侵了.或是你的 Linux 系统由於硬件关系 (不论是天灾还是人祸) 而挂掉了!这个时候,请问如 ...
- 【JavaScript 进阶之旅 DOM篇 第九章】鼠标行为、pageX|Y封装、拖拽事件封装
文章目录 一.鼠标行为 1.clientX/Y 2.pageX/Y 3.screenX/Y 4.offsetX/Y 5.layerX/Y(不推荐使用) 6.x/y(不推荐使用) 二.pageX|Y封装 ...
- 鸟哥的Linux私房菜(基础篇)- 第二十六章、Linux 核心编译与管理
第二十六章.Linux核心编译与管理 最近升级日期:2009/09/18 我们说的 Linux 其实指的就是核心 (kernel) 而已.这个核心控制你主机的所有硬件并提供系统所有的功能,所以说,他重 ...
- java语言程序设计基础篇课后答案_《Java语言程序设计:基础篇》课后复习题答案-第十五章.pdf...
<Java语言程序设计:基础篇>课后复习题答案-第十五章 Chapter15Graphics 1. Theycoordinateshouldincreaseandthexcoordinat ...
- 服务器存储满了进不去系统,解决PC常见问题 篇四十五:建议收藏!手贱升级进不去系统?两步简单恢复黑群晖!...
解决PC常见问题 篇四十五:建议收藏!手贱升级进不去系统?两步简单恢复黑群晖! 2021-07-19 16:40:32 47点赞 302收藏 15评论 创作立场声明:本文属于原创文章,无任何利益关系, ...
- android相册幻灯片功能,玩机教程 篇四十五:「MIUI玩机技巧63」MIUI相册新增“幻灯片播放”功能...
玩机教程 篇四十五:「MIUI玩机技巧63」MIUI相册新增"幻灯片播放"功能 2020-02-17 16:15:35 0点赞 0收藏 0评论 本帖主要解决2大问题: 1) 功能科 ...
- 两组数据的偏差率_GWT测试报告 篇七十五:隐患难忽视,RIVAL 3 WIRELESS精准度LOD测试...
GWT测试报告 篇七十五:隐患难忽视,RIVAL 3 WIRELESS精准度LOD测试 2020-12-07 18:35:00 4点赞 2收藏 5评论 你是AMD Yes党?还是intel和NVIDI ...
- LINUX学习基础篇(十五)软件包管理
LINUX学习基础篇(十五)软件包管理 软件包管理 软件包分类 源码包 二进制包 选择 依赖性 rpm包安装 rpm包命名规则 rpm包安装和卸载 服务命令 rpm查询命令 验证 数字证书 rpm中文 ...
最新文章
- java学习笔记(十)----String类和StringBuffer类
- word中光标选择一列文字_Word中文字排版对齐很难?只因你没掌握这几招排版技巧!...
- seo从入门到精通_SEO入门到精通(七):SEO工作的流程是什么?
- 英语语法---动名词短语详解
- Eclipse安装AmaterasUML
- 计算机不同用户信息互通吗,迷你世界电脑版和手机版通用吗 二者账号数据互通吗...
- server2008R2平台部署exchange2010
- 如何在Slack里连接微软One Drive
- 使用一些可选的将字符串配置属性转换为其他类型
- LeetCode-148:排序链表
- java 获取文件所在的文件夹_带你0基础编写一个Java小程序,领略Java程序从编写到编译再到运行的全流程...
- MySQL无法启动 服务没有报告任何错误
- 随想录(编写简单资源管理代码)
- C#相关时间DateTime格式化
- 心情随笔(四):重新审视自我
- html模拟鼠标点击图标,易语言模拟鼠标点击实现方法
- R语言使用dlnorm函数生成对数正态分布密度数据、使用plot函数可视化对数正态分布密度数据(logarithmic normal distribution)
- java中高级面试_中高级面试常问:Java面向对象设计的六大原则
- putty连接不上该怎么办
- SpringBoot+海康威视摄像头实现在前端的预览