JavaScript 标准之 Map对象
概览:
- 前言
- 定义
- 语法
- 描述
- 属性
- Map实例
前沿
一直以来使用数组和对象来定义数据模型,前几天在翻阅ES6语法的时候,突然发现有一种Map对象对操作键值对特别好用,而且代码更简洁明了,简直太棒了。今天,我们就来一步步了解什么是Map对象,详细给大家介绍一下Map对象的属性和方法。希望大家以后再数据操纵方法多一种解决问题的方法,这是ECMAScript 6 新增的数据结构。
定义
Map对象保存键/值对,是键/值对的集合。任何值(对象或者原始值) 都可以作为一个键或一个值。Object结构提供了“字符串—值”的对应,Map结构提供了“值—值”的对应。
语法
mapObj = new Map([iterable]);
iterable 可以是一个数组或者其他 iterable 对象,其元素或为键值对,或为两个元素的数组。 每个键值对都会添加到新的 Map。null 会被当做 undefined。
描述
- 集合中的键和值可以是任何类型。如果使用现有键向集合添加值,则新值会替换旧值。
- Object 和 Map 对象的对比:
相似点: 都允许你按键存取一个值、删除键、检测一个键是否绑定了值。
不同点:
1. 一个对象的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值,包括函数、对象、基本类型。
2. Map 中的键值是有序的,而添加到对象中的键则不是。因此,当对它进行遍历时,Map对象是按插入的顺序返回键值。
3. 通过 size 属性直接获取一个 Map 的键值对个数,而 Object 的键值对个数只能手动计算。
4. Map 是可迭代的,而 Object 的迭代需要先获取它的键数组然后再进行迭代。
5. Object 都有自己的原型,所以原型链上的键名有可能和对象上的键名产生冲突。虽然 ES5 开始可以用 map = Object.create(null) 来创建一个没有原型的对象,但是这种用法不太常见。
6. Map 在频繁增删键值对的场景下会有些性能优势。
属性
下表列出了Map对象的属性
属性 | 描述 |
---|---|
构造函数 -get Map[@@species] | 指定创建映射的函数,本构造函数用于创建派生对象。 |
原型(Map.prototype) | 为映射返回对原型的引用, 表示Map构造器的原型。 允许添加属性从而应用于所有的Map对象。 |
size (Map.length) | 返回映射中的元素数。 |
Map实例
所有的Map实例都会继承自Map.prototype。
属性
下表列出了Map对象实例的属性
属性 | 描述 |
---|---|
Map.prototype.constructor | 返回一个函数,它创建了实例的原型。默认是Map函数。 |
Map.prototype.size | 返回Map对象的键/值对的数量。 |
方法
下表列出了Map对象实例的方法
方法 | 描述 |
---|---|
Map.prototype.clear() | 移除Map对象的所有键/值对。 |
Map.prototype.delete(key) | 移除指定键相关联的值,并且返回该值,该值在之前会被Map.prototype.has(key)返回为true。之后再调用Map.prototype.has(key)会返回false。 |
Map.prototype.entries() | 返回一个新的 Iterator 对象,它按插入顺序包含了Map对象中每个元素的 [key, value] 数组。 |
Map.prototype.forEach(callbackFn[ , thisArg]) | 按插入顺序,为 Map对象里的每一键值对调用一次callbackFn函数。如果为forEach提供了thisArg,它将在每次回调中作为this值。 |
Map.prototype.get(key) | 返回指定键的值,如果不存在返回undefined。 |
Map.prototype.has(key) | 返回一个布尔值,表示Map实例是否包含键对应的值,如果包含指定元素,返回true。 |
Map.prototype.keys() | 返回一个新的 Iterator对象,它按插入顺序包含了Map对象中每个元素的键。 |
Map.prototype.set(key, value) | 设置Map对象中指定键的值,并返回该Map对象。 |
Map.prototype.values() | 返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的值 。 |
Map.prototype[@@iterator] | 返回一个新的Iterator对象,它按插入顺序包含了Map对象中每个元素的 [key, value] 数组。 |
示例
Map对象类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
let a = new Map(); let b = {p: 'Hello World'}; a.set(b,"content"); a.get(b); //"content" a.has(b); //true a.delete(b); //true a.has(b); //false
作为构造函数,Map也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。
let map = new Map([ ['first', 'aaaaaaaaaaaaa'], ['second','bbbbbbbbbbbbb'] ]); map.size(); // 2 map.has('first'); // true map.get('first'); // "aaaaaaaaaaaaa" map.has('second'); // true map.get('second'); // "bbbbbbbbbbbbb"
如果对同一个键多次赋值,后面的值将覆盖前面的值。
let map = new Map(); map.set(1, 'aaa'); map.set(1, 'bbb'); map.get(1) // "bbb"
如果读取一个未知的键,则返回undefined。!!!注意,只有对同一个对象的引用,Map结构才将其视为同一个键。Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。这就解决了同名属性碰撞(clash)的问题,我们扩展别人的库的时候,如果使用对象作为键名,就不用担心自己的属性与原作者的属性同名。
let map =new Map(); map.get('abc'); // undefined map.set(['a'], 555); map.get(['a']) // undefined const k1 = ['a']; const k2 = ['a']; map .set(k1, 111) .set(k2, 222); map.get(k1); // 111 map.get(k2); // 222
Map.clear() 方法清除所有成员,没有返回值。
let map = new Map(); map.set('foo', true); map.set('bar', false); map.size(); // 2 map.clear(); map.size(); // 0
Map对象遍历方法示例
let map = new Map([ ['first', 'aaa'], ['second', 'bbb'], ]); // map.keys()方法 for (let key of map.keys()) { console.log(key); } // first // second // map.values()方法 for (let value of map.values()) { console.log(value); } // "aaa" // "bbb" //map.entries() 方法 for (let item of map.entries()) { console.log(item[0], item[1]); } // "first" "aaa" // "second" "bbb" //等同于使用map.entries()方法 for (let [key, value] of map) { console.log(key, value); } // "first" "aaa" // "second" "bbb" //数组结构可以使用扩展运算符(...) [...map.keys()] //["first","second"] [...map.values()] // ["aaa","bbb"] [...map.entries()] // [["first", "aaa"],["second", "bbb"]] [...map] //[["first", "aaa"],["second", "bbb"]]
结合数组的map() 和filter()方法,可以实现对Map的遍历和过滤(Map本身没有map()和filter()方法)
let myMap = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]); let newMap = new Map( [...myMap].filter(([key, value]) => value < 3) ); // Map(2) {"thing1" => 1, "thing2" => 2} let newMap2 = new Map( [...myMap].map(([key, value]) => [key, value * 2]) ); // Map(3) {"thing1" => 2, "thing2" => 4, "thing3" => 6}
Map对象还有一个forEach方法,与数组的forEach方法类似,也可以实现遍历。
let map = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]); map.forEach(function(value, key, map) { console.log("Key: %s, Value: %s", key, value); }); // Key: thing1, Value: 1 // Key: thing2, Value: 2 // Key: thing3, Value: 3
forEach方法还可以接受第二个参数,用来绑定this。
let map = new Map([["thing1", 1], ["thing2", 2], ["thing3", 3]]); let reporter = { report: function(key, value) { console.log("Key: %s, Value: %s", key, value); } }; map.forEach(function(value, key, map) { this.report(key, value); }, reporter); // Key: thing1, Value: 1 // Key: thing2, Value: 2 // Key: thing3, Value: 3
参考文献
- 【美】MDN Web docs 之 Map
- 【美】Microsoft Developer Network 之 Map对象(JavaScript)
- 【中】阮一峰 ECMAScript 6 入门
转载时请注明:来自w-rain的个人博客
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
白话SpringCloud | 第七章:分布式配置中心的使用
前言 介绍完服务的容错保护处理,接下来我们来了解下关于分布式配置中心的相关知识和使用。众所周知,随着项目的越来越多,日益庞大,每个子项目都会伴随着不同的配置项,于此也就多了很多的配置文件。倘若某些配置信息修改,可能就会伴随着一系列配置文件的更新和相应服务的重启操作了。这对于实施而言,也是噩梦一般的存在,增加了一系列运维成本,也会无形中提高出错的机率。所以在微服务越来越多时,就会引入今天要讲解的分布式配置中心,它就是来解决此类问题的。话不多说,开始吧~ 一点知识 为什么要统一管理微服务配置 在写这篇文章之前,在公众号里有推送了一篇《为什么需要分布式配置中心》的文章。里面也大致说明了,大家可以看一看。简单来说,就是随着业务的发展、微服务架构的升级,服务的数量、程序的配置日益增多(各种微服务、各种服务器地址、各种参数),传统的配置文件方式和数据库的方式已无法满足开发人员对配置管理的要求,即 安全性:配置跟随源代码保存在代码库中,容易造成配置泄漏; 时效性:修改配置,需要重启服务才能生效; 局限性:无法支持动态调整:例如日志开关、功能开关; 其实说白了,就是当业务需求有变更时,可以通过修改配置...
- 下一篇
RocketMQ双Master集群搭建
机器准备 2台独立的linux主机, 内网IP分别为: 172.31.175.142/143 172.31.175.142 NameServer1、 Broker Master1 172.31.175.143 NameServer2、 Broker Master2 安装配置 安装 下载二进制版本解压即可 wget http://mirrors.hust.edu.cn/apache/rocketmq/4.3.0/rocketmq-all-4.3.0-bin-release.zip unzip rocketmq-all-4.3.0-bin-release.zip -d ~ cd ~ mv rocketmq-all-4.3.0-bin-release rocketmq 启动NameServer 命令的std输出使用默认的运行日志 mkdir -p ~/logs/rocketmqlogs nohup sh bin/mqnamesrv >~/logs/rocketmqlogs/namesrv.log 2>&1 & tail -100f ~/logs/roc...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- Red5直播服务器,属于Java语言的直播服务器
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Hadoop3单机部署,实现最简伪集群
- CentOS8编译安装MySQL8.0.19