我的编程空间,编程开发者的网络收藏夹
学习永远不晚

在什么时候适合使用Map

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

在什么时候适合使用Map

本篇内容介绍了“在什么时候适合使用Map”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

「Map」映射是一种经典的数据结构类型,其中数据以 「key/value」 的键值对形式存在

 MapObject
默认值默认不包含任何值,只包含显式插入的键一个 Object 有一个原型,原型上的键名有可能和自己对象上设置的键名冲突
类型任意String 或 Symbol
长度键值对个数通过 size 属性获取键值对个数只能手动计算
性能频繁增删键值对的场景下表现更好频繁添加和删除键值对的场景下未作出优化

Map 基本用法

const testMap = new Map()  let str = '今天不学习',      num = 666,      keyFunction = function () {},      keySymbol = Symbol('Web'),      keyNull = null,      keyUndefined = undefined,      keyNaN = NaN  //添加键值对  //基本用法  testMap.set('key', 'value') // Map(1) {"key" => "value"}  testMap.set(str, '明天变辣鸡')  testMap.set(num, '前端Sneaker')  testMap.set(keyFunction, '你的函数写的好棒棒哦')  testMap.set(keySymbol, '大前端')  testMap.set(keyNull, '我是个Null')  testMap.set(keyUndefined, '我是个Undifined')  testMap.set(keyNaN, '我是个NaN')  testMap.get(function () {}) //undefined  testMap.get(Symbol('Web')) //undefined  //虽然NaN !== NaN 但是作为Map键名并无区别  testMap.get(NaN) //"我是个NaN"  testMap.get(Number('NaN')) //"我是个NaN"

除了NaN比较特殊外,其他「Map」的get方法都是通过对比键名是否相等(===)来获取,不相等则返回undefined

比较 Map 和 Object

定义

//Map  const map = new Map();  map.set('key', 'value'); // Map(1) {"key" => "value"}  map.get('key'); // 'value'  //Object  const someObject = {};  someObject.key = 'value';  someObject.key; // 'value'

这里可以明显看出其实其定义行为是十分相似的,想必看到这里大家还没看出来「Map」到底在何时使用才是最佳实践,别急接着来。

键名类型

JavaScript 「Object」只接收两种类型的键名 String 和 Symbol,你可以使用其他类型的键名,但是最终 JavaScript 都会隐式转换为字符串

const obj = {}  //直接看几种比较特殊的键名  obj[true] = 'Boolean'  obj[1] = 'Number'  obj[{'前端':'Sneaker'}] = '666'  Object.keys(obj) // ["1", "true", "[object Object]"]

再来看看 「Map」 的,其接收任何类型的键名并保留其键名类型 (此处简单举例,详细可看文章开头「Map」基本使用)

const map = new Map();  map.set(1, 'value');  map.set(true, 'value');  map.set({'key': 'value'}, 'value');  for (const key of map.keys()) {    console.log(key);  }  // 1  // true  // {key: "value"}  //除此之外,Map还支持正则作为键名  map.set(/^1[3456789]\d{9}$/,'手机号正则')  //Map(1) {/^1[3456789]\d{9}$/ => "手机号正则"}

「Map」支持正则表达式作为键名,这在Object是不被允许的直接报错

原型 Prototype

「Object」不同于「Map」,它不仅仅是表面所看到的。「Map」只包含你所定义的键值对,但是「Object」对象具有其原型中的一些内置属性

const newObject = {};  newObject.constructor; // ƒ Object() { [native code] }

如果操作不当没有正确遍历对象属性,可能会导致出现问题,产生你意料之外的 bug

在什么时候适合使用Map

const countWords = (words) => {    const counts = { };    for (const word of words) {      counts[word] = (counts[word] || 0) + 1;    }    return counts;  };  const counts = countWords(['constructor', 'creates', 'a', 'bug']);  // {constructor: "function Object() { [native code] }1", creates: 1, a: 1, bug: 1}

这个例子灵感来源于《Effective TypeScript》[1]一书

迭代器

「Map」 是可迭代的,可以直接进行迭代,例如forEach循环或者for...of...循环

//forEach  const map = new Map();  map.set('key1', 'value1');  map.set('key2', 'value2');  map.set('key3', 'value3');  map.forEach((value, key) => {    console.log(key, value);  });  // key1 value1  // key2 value2  // key3 value3  //for...of...  for(const entry of map) {    console.log(entry);  }  // ["key1", "value1"]  // ["key2", "value2"]  // ["key3", "value3"]

但是对于「Object」是不能直接迭代的,当你尝试迭代将导致报错

在什么时候适合使用Map

const object = {    key1: 'value1',    key2: 'value2',    key3: 'value3',  };  for(const entry of object) {    console.log(entry);  }  // Uncaught TypeError: object is not iterable

这时候你就需要一个额外的步骤来检索其键名、键值或者键值对

for(const key of Object.keys(object)) {    console.log(key);  }  // key1  // key2  // key3  for(const value of Object.values(object)) {    console.log(value); }  // value1  // value2  // value3  for(const entry of Object.entries(object)) {    console.log(entry);  }  // ["key1", "value1"]  // ["key2", "value2"]  // ["key3", "value3"]  for(const [key,value] of Object.entries(object)) {    console.log(key,value);  }  //"key1", "value1"  //"key2", "value2"  //"key3", "value3"

当然也可以使用for...in...进行遍历循环键名

for(const key in object) {    console.log(key);  }  // key1  // key2  // key3

元素顺序和长度

Map 保持对长度的跟踪,使其能够在O(1)复杂度中进行访问

const map = new Map();  map.set('key1', 'value1');  map.set('key2', 'value2');  map.set('key3', 'value3');  map.size; // 3

而另一方面,对于「Object」而言,想要获得对象的属性长度,需要手动对其进行迭代,使其为O(n)复杂度,属性长度为n

在上文提及的示例中,我们可以看到「Map」始终保持按插入顺序返回键名。但「Object」却不是。从 ES6 开始,String和Symbol键是按顺序保存起来的,但是通过隐式转换保存成String的键就是乱序的

const object = { };  object['key1'] = 'value1';  object['key0'] = 'value0';  object; // {key1: "value1", key0: "value0"}  object[20] = 'value20';  object; // {20: "value20", key1: "value1", key0: "value0"}  Object.keys(object).length; //3

Object/Map 何为最佳实践

如上就是 「Map」 和 「Object」 的基本区别,在解决问题考虑两者的时候就需要考虑两者的区别。

  •  当插入顺序是你解决问题时需要考虑的,并且当前需要使用除 String 和 Symbol 以外的键名时,那么 「Map」 就是个最佳解决方案

  •  如果需要遍历键值对(并且需要考虑顺序),那我觉得还是需要优先考虑 「Map」。

  •  Map是一个纯哈希结构,而Object不是(它拥有自己的内部逻辑)。Map 在频繁增删键值对的场景下表现更好,性能更高。因此当你需要频繁操作数据的时候也可以优先考虑 Map

  •  再举一个实际的例子,比如有一个自定义字段的用户操作功能,用户可以通过表单自定义字段,那么这时候最好是使用 Map,因为很有可能会破坏原有的对象 

const userCustomFields = {    'color':    'blue',    'size':     'medium',    'toString': 'A blue box'  };

此时用户自定义的 toString 就会破坏到原有的对象 而 「Map」 键名接受任何类型,没有影响

function isMap(value) {    return value.toString() === '[object Map]';  }  const actorMap = new Map(); actorMap.set('name', 'Harrison Ford');  actorMap.set('toString', 'Actor: Harrison Ford');  // Works!  isMap(actorMap); // => true
  •  当你需要处理一些属性,那么 「Object」 是完全受用的,尤其是需要处理 JSON 数据的时候。由于 「Map」 可以是任意类型,因此没有可以将其转化为 JSON 的原生方法。 

var map = new Map()  map.set('key','value')  JSON.stringify(map)  //"{}"
  •  当你需要通正则表达式判断去处理一些业务逻辑时,「Map」将是你的最佳解决方案 

const actions = ()=>{    const functionA = ()=>{}    const functionB = ()=>{}    const functionC = ()=>{}    returnnewMap([      [/^guest_[1-4]$/,functionA],      [/^guest_5$/,functionB],      [/^guest_.*$/,functionC],      //...    ])  } const onButtonClick = (identity,status)=>{    let action = [...actions()].filter(([key,value])=>(key.test(`${identity}_${status}`)))    action.forEach(([key,value])=>value.call(this))  }

利用数组循环的特性,符合正则条件的逻辑都会被执行,那就可以同时执行公共逻辑和单独逻辑,因为正则的存在,你可以打开想象力解锁更多的玩法,更多相关 Map 用法样例可以查看JavaScript 复杂判断的更优雅写法

“在什么时候适合使用Map”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

在什么时候适合使用Map

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

什么时候适合使用 C++ 函数单元测试?

函数单元测试是一种自动化测试技术,用于隔离测试 c++++ 函数的预期行为。适用于以下场景:验证函数行为检查边界条件检测错误重构代码作为文档说明何时使用 C++ 函数单元测试函数单元测试是一种对 C++ 函数进行隔离测试的自动化测试技术。
什么时候适合使用 C++ 函数单元测试?
2024-04-24

java中什么时候使用static

什么时候使用:当一个方法或者变量需要初始化加载,或者是经常被调用的时候可以加上static。用static修饰的方法可以用类名直接调用,不用的一定要先实例化一个对象然后才可以调用。不足之处:初始化加载,比较占内存,所以不经常用的方法,不建议加此关键字。如果你需
java中什么时候使用static
2017-08-26

什么时候使用Lambda函数?

原文来自:1前言Python 中定义函数有两种方法,一种是用常规方式 def 定义,函数要指定名字,第二种是用 lambda 定义,不需要指定名字,称为 Lambda 函数。Lambda 函数又称匿名函数,匿名函数就是没有名字的函数,函数没
2023-06-02

c++中endl什么时候使用

std::endl 用于将换行符写入流,通常在需要显式结束行时使用。它强制刷新流并避免缓冲行为。替代方法包括直接写入 '\n' 字符或使用 std::flush 手动刷新流。什么时候使用 std::endl 在 C++ 中简答:std:
c++中endl什么时候使用
2024-04-28

java中什么时候使用事务

什么时候使用事务?1、如果实际的业务中,需要将一条数据同时存放到两张表中, 并且要求两张表中的数据同步,那么此时就需要使用事务管理机制,保证数据同步。如果出现错误情况,比如表一插入数据成功,表二插入数据失败,那么就回滚,终止数据持久化操作。2、金融行业的软件开
java中什么时候使用事务
2016-07-06

VPS主机适合什么网站使用

VPS主机适合中小型网站和企业网站使用,特别是对于需要更高性能和资源控制的网站。这包括电子商务网站、博客、论坛、社交网络、在线游戏等。VPS主机也适合需要定制化配置和更高安全性的网站。如果您的网站流量较大或需要更高的稳定性和可靠性,VPS主
VPS主机适合什么网站使用
2024-04-19

Java消息队列什么时候使用

本篇内容主要讲解“Java消息队列什么时候使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java消息队列什么时候使用”吧!何时需要消息队列当你需要使用消息队列时,首先需要考虑它的必要性。可以
2023-06-04

什么时候需要使用HTTPS代理

本篇文章给大家分享的是有关什么时候需要使用HTTPS代理,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。HTTPS是HTTP的安全版本,它在HTTP上建立SSL加密层并加密传输的
2023-06-25

Java匿名内部类在什么时候用

Java匿名内部类通常在以下情况下使用:1. 当一个类只需要使用一次,并且这个类没有名字,可以使用匿名内部类来实现。这样可以避免创建一个单独的类文件。2. 当一个接口只有一个方法需要实现时,可以使用匿名内部类来实现接口的方法。这种情况下,可
2023-08-15

什么时候应该使用 golang 函数?

何时使用 go 函数?需要将代码分解成较小的块。需要重复使用代码。需要将代码逻辑封装到一个可重用的模块中。何时使用 Go 函数Go 中的函数是一种封装代码并将代码块组织在一起的方法。函数有多个优点,包括:可重用性:函数可以重复使用,避免重
什么时候应该使用 golang 函数?
2024-04-25

java移位运算符在什么时候用

Java移位运算符用于对一个数的二进制位进行移动。它们通常在以下情况下使用:1. 位运算:移位运算符可用于对整数进行位运算,如按位与、按位或和按位异或等操作。2. 优化算法:移位运算符可以用于优化某些算法,例如在计算机图形学中,可以使用位移
2023-08-29

捷克服务器适合什么用户使用

捷克服务器适合以下类型的用户使用:网站开发者:捷克服务器提供稳定的网络连接和高性能的服务器硬件,适合网站开发者搭建和部署网站。游戏玩家:捷克服务器提供低延迟的网络连接和高性能的服务器硬件,适合游戏玩家在游戏中获得更好的游戏体验。企业用户:捷
捷克服务器适合什么用户使用
2024-05-13

编程热搜

目录