ES6集合:使用地图,设置,弱图,弱点
本文探讨了四个新的ES6集合以及它们带来的好处。
大多数主要的编程语言都有几种类型的数据集合。Python有列表、元组和字典。Java有列表、集合、映射、队列。Ruby有哈希和数组。到目前为止,JavaScript只有数组。对象和数组是JavaScript的得力助手。ES6引入了四个新的数据结构,它们将增强语言的强大功能和表达能力:Map、Set、WeakSet和WeakMap。
关键要点
- ES6引入了四个新的数据结构:Map、Set、WeakSet和WeakMap。这些集合允许更具表达性和功能强大的JavaScript编程。
- ES6中的Map和Set是任何类型的键值对的集合。它们针对快速检索进行了优化,并提供添加、删除和循环遍历值的方法。但是,它们对对象持有强引用,如果对象很大且不再需要,则可能代价很高。
- ES6还引入了WeakMap和WeakSet,它们类似于Map和Set,但对对象持有弱引用。这意味着当这些对象不再需要时,可以对其进行垃圾回收,这对于内存管理非常有益。
- 虽然新的ES6集合提供了更大的灵活性,但在许多情况下,JavaScript对象仍然可以用作集合。在决定是否使用对象或键控集合时,开发人员应考虑诸如需要动态键查找、值的互换性和添加或删除键值对的频率等因素。
寻找JavaScript HashMap
HashMap、字典和哈希是各种编程语言存储键值对的几种方法,这些数据结构针对快速检索进行了优化。
在ES5中,JavaScript对象(只是具有键和值的属性的任意集合)可以模拟哈希,但是使用对象作为哈希有几个缺点。
缺点#1:ES5中的键必须是字符串
JavaScript对象属性键必须是字符串,这限制了它们作为不同数据类型键值对集合的能力。当然,您可以将其他数据类型强制转换为字符串,但这会增加额外的工作。
缺点#2:对象并非天生可迭代
对象并非设计为集合,因此没有有效的方法来确定对象有多少属性。(例如,Object.keys速度很慢)。当您循环遍历对象的属性时,您还会获得其原型属性。您可以向所有对象添加可迭代属性,但并非所有对象都旨在用作集合。您可以使用for … in循环和hasOwnProperty()方法,但这只是一个变通方法。当您循环遍历对象的属性时,属性不一定会按照插入的顺序检索。
缺点#3:内置方法冲突的挑战
对象具有内置方法,如constructor、toString和valueOf。如果将其中一个添加为属性,则可能导致冲突。您可以使用Object.create(null)创建一个裸对象(不继承自object.prototype),但这仍然只是一个变通方法。
ES6包含新的集合数据类型,因此不再需要使用对象并忍受它们的缺点。
使用ES6 Map集合
Map是我们将要检查的第一个数据结构/集合。Map是任何类型的键值对的集合。创建新的Map、添加/删除值、循环遍历键/值以及有效地确定其大小很容易。以下是关键方法:
创建映射并使用常用方法
const map = new Map(); // 创建一个新的Map map.set('hobby', 'cycling'); // 设置键值对 const foods = { dinner: 'Curry', lunch: 'Sandwich', breakfast: 'Eggs' }; // 新对象 const normalfoods = {}; // 新对象 map.set(normalfoods, foods); // 设置两个对象作为键值对 for (const [key, value] of map) { console.log(`${key} = ${value}`); // hobby = cycling [object Object] = [object Object] } map.forEach((value, key) => { console.log(`${key} = ${value}`); }, map); // hobby = cycling [object Object] = [object Object] map.clear(); // 清除键值对 console.log(map.size === 0); // True
在JSBin上运行此示例
使用Set集合
Set是有序的值列表,不包含重复项。Set不是像数组那样被索引,而是使用键访问。Set已经存在于Java、Ruby、Python和许多其他语言中。ES6 Set与其他语言中的Set之间的一个区别是,顺序在ES6中很重要(在许多其他语言中并非如此)。以下是关键的Set方法:
const planetsOrderFromSun = new Set(); planetsOrderFromSun.add('Mercury'); planetsOrderFromSun.add('Venus').add('Earth').add('Mars'); // 可链式方法 console.log(planetsOrderFromSun.has('Earth')); // True planetsOrderFromSun.delete('Mars'); console.log(planetsOrderFromSun.has('Mars')); // False for (const x of planetsOrderFromSun) { console.log(x); // 输入和输出顺序相同 - Mercury Venus Earth } console.log(planetsOrderFromSun.size); // 3 planetsOrderFromSun.add('Venus'); // 尝试添加重复项 console.log(planetsOrderFromSun.size); // 仍然是3,没有添加重复项 planetsOrderFromSun.clear(); console.log(planetsOrderFromSun.size); // 0
在JSBin上运行此示例
弱集合、内存和垃圾回收
JavaScript垃圾回收是一种内存管理形式,其中不再引用的对象会自动删除,并且其资源会被回收。
Map和Set对对象的引用是强持有的,并且不允许垃圾回收。如果map/set引用不再需要的大的对象(例如已经从DOM中删除的DOM元素),这可能会变得很昂贵。
为了解决这个问题,ES6还引入了两个新的弱集合,称为WeakMap和WeakSet。这些ES6集合是“弱”的,因为它们允许不再需要的对象从内存中清除。
WeakMap
WeakMap是我们介绍的第三个新的ES6集合。WeakMap类似于普通的Map,但方法较少,并且在垃圾回收方面存在上述差异。
const aboutAuthor = new WeakMap(); // 创建新的WeakMap const currentAge = {}; // 键必须是对象 const currentCity = {}; // 键必须是对象 aboutAuthor.set(currentAge, 30); // 设置键值 aboutAuthor.set(currentCity, 'Denver'); // 键值可以是不同数据类型 console.log(aboutAuthor.has(currentCity)); // 测试WeakMap是否包含键 aboutAuthor.delete(currentAge); // 删除键
使用案例
WeakMap有几个流行的用例。它们可以用来保持对象的私有数据私有,也可以用来跟踪DOM节点/对象。
私有数据用例
以下示例来自JavaScript专家Nicholas C. Zakas:
var Person = (function() { var privateData = new WeakMap(); function Person(name) { privateData.set(this, { name: name }); } Person.prototype.getName = function() { return privateData.get(this).name; }; return Person; }());
在这里使用WeakMap简化了保持对象数据私有的过程。可以引用Person对象,但是如果没有特定的Person实例,则不允许访问privateDataWeakMap。
DOM节点用例
Google Polymer项目在一个名为PositionWalker的代码片段中使用WeakMap。
PositionWalker跟踪DOM子树中的位置,作为当前节点和该节点内的偏移量。
WeakMap用于跟踪DOM节点的编辑、删除和更改:
const map = new Map(); // 创建一个新的Map map.set('hobby', 'cycling'); // 设置键值对 const foods = { dinner: 'Curry', lunch: 'Sandwich', breakfast: 'Eggs' }; // 新对象 const normalfoods = {}; // 新对象 map.set(normalfoods, foods); // 设置两个对象作为键值对 for (const [key, value] of map) { console.log(`${key} = ${value}`); // hobby = cycling [object Object] = [object Object] } map.forEach((value, key) => { console.log(`${key} = ${value}`); }, map); // hobby = cycling [object Object] = [object Object] map.clear(); // 清除键值对 console.log(map.size === 0); // True
WeakSet
WeakSet是其元素在不再需要它们引用的对象时可以进行垃圾回收的Set集合。WeakSet不允许迭代。它们的用例相当有限(至少目前是这样)。大多数早期采用者说WeakSet可以用来标记对象而无需修改它们。ES6-Features.org有一个从WeakSet添加和删除元素的示例,以便跟踪对象是否已被标记:
const planetsOrderFromSun = new Set(); planetsOrderFromSun.add('Mercury'); planetsOrderFromSun.add('Venus').add('Earth').add('Mars'); // 可链式方法 console.log(planetsOrderFromSun.has('Earth')); // True planetsOrderFromSun.delete('Mars'); console.log(planetsOrderFromSun.has('Mars')); // False for (const x of planetsOrderFromSun) { console.log(x); // 输入和输出顺序相同 - Mercury Venus Earth } console.log(planetsOrderFromSun.size); // 3 planetsOrderFromSun.add('Venus'); // 尝试添加重复项 console.log(planetsOrderFromSun.size); // 仍然是3,没有添加重复项 planetsOrderFromSun.clear(); console.log(planetsOrderFromSun.size); // 0
Map所有事物?记录与ES6集合
Map和Set是键值对的漂亮的新ES6集合。也就是说,JavaScript对象仍然可以在许多情况下用作集合。除非情况需要,否则无需切换到新的ES6集合。
MDN有一个很好的问题列表,用于确定何时使用对象或键控集合:
- 键通常直到运行时才知道吗?您需要动态查找它们吗?
- 所有值都具有相同的类型,并且可以互换使用吗?
- 您是否需要不是字符串的键?
- 经常添加或删除键值对吗?
- 您是否有任意数量(易于更改)的键值对?
- 集合是否被迭代?
新的ES6集合产生更易用的JavaScript
JavaScript集合以前非常有限,但这已通过ES6得到纠正。这些新的ES6集合将增强语言的强大功能和灵活性,并简化采用它们的JavaScript开发人员的任务。
本文是来自Microsoft技术布道者和DevelopIntelligence关于实用JavaScript学习、开源项目和互操作性最佳实践(包括Microsoft Edge浏览器和新的EdgeHTML渲染引擎)的Web开发系列的一部分。DevelopIntelligence通过appendTo(其专注于前端的博客和课程网站)提供JavaScript培训和React培训课程。
我们鼓励您在包括Microsoft Edge(Windows 10的默认浏览器)在内的各种浏览器和设备上进行测试,可以使用dev.microsoftedge.com上的免费工具,包括EdgeHTML问题跟踪器,您可以在其中报告或搜索EdgeHTML问题,例如网站渲染或标准合规性问题。此外,请访问Edge博客,以获取来自Microsoft开发人员和专家的最新信息。
关于ES6集合的常见问题解答 (FAQ):Map、Set、WeakMap、WeakSet
JavaScript ES6中Map和WeakMap的主要区别是什么?
在JavaScript ES6中,Map和WeakMap都用于存储键值对。但是,它们之间存在一些显着差异。首先,在Map中,键可以是任何类型,而在WeakMap中,键必须是对象。其次,Map具有size属性,允许您检查键值对的数量,但WeakMap没有此属性。最后,Map对键对象持有强引用,这意味着只要Map存在,它们就没有资格进行垃圾回收。另一方面,WeakMap对键对象持有弱引用,这意味着如果对对象没有其他引用,则可以对其进行垃圾回收。
如何在JavaScript ES6中迭代WeakMap或WeakSet?
与Map和Set不同,WeakMap和WeakSet没有迭代其元素的方法。这是因为它们旨在对它们的键(WeakMap)或值(WeakSet)持有弱引用,这意味着这些可以在任何时间进行垃圾回收。因此,无法保证在尝试迭代元素时元素仍然存在。如果您需要迭代集合,则应改用Map或Set。
我可以在WeakMap或WeakSet中使用原始数据类型作为键吗?
不可以,您不能在WeakMap或WeakSet中使用原始数据类型作为键。这些集合中的键必须是对象。这是因为WeakMap和WeakSet对它们的键持有弱引用,这意味着如果对它们没有其他引用,则可以对键进行垃圾回收。原始数据类型(例如数字和字符串)不会像对象那样进行垃圾回收,因此它们不能用作这些集合中的键。
为什么我应该使用WeakMap或WeakSet而不是Map或Set?
WeakMap和WeakSet具有一些独特的特性,在某些情况下,它们可能比Map或Set更合适。因为它们对它们的键(WeakMap)或值(WeakSet)持有弱引用,所以当它们不再使用时,可以对其进行垃圾回收。如果您想将其他数据与对象关联,但又不想阻止对象在不再需要时进行垃圾回收,这将非常有用。此外,因为WeakMap和WeakSet没有迭代其元素的方法,所以它们可以为它们存储的数据提供一定程度的隐私。
当WeakMap或WeakSet中的键被垃圾回收时会发生什么?
当WeakMap或WeakSet中的键被垃圾回收时,集合中的相应条目会自动删除。这是因为这些集合对它们的键持有弱引用,这意味着当它们不再使用时,可以对键进行垃圾回收。此功能对于管理JavaScript应用程序中的内存非常有用,因为它确保与不再使用的对象关联的数据也会被清除。
我可以使用WeakMap或WeakSet来存储临时数据吗?
是的,WeakMap和WeakSet非常适合存储临时数据。因为它们对它们的键(WeakMap)或值(WeakSet)持有弱引用,所以当它们不再使用时,可以对其进行垃圾回收。这意味着当键被垃圾回收时,存储在这些集合中的数据也会被清除。这对于存储仅在短时间内需要的有用,因为您不必担心手动清理它。
如何检查WeakMap或WeakSet是否包含某个键或值?
您可以使用has方法来检查WeakMap或WeakSet是否包含某个键。此方法返回一个布尔值,指示该键是否存在于集合中。但是,请记住,您不能使用此方法来检查WeakSet中的某个值,因为此集合中的值是不可访问的。
我可以从WeakMap或WeakSet中删除条目吗?
是的,您可以使用delete方法从WeakMap中删除条目。此方法删除与给定键关联的条目,并返回一个布尔值,指示该键是否存在于集合中。但是,您不能从WeakSet中删除条目,因为此集合没有delete方法。
我可以清除WeakMap或WeakSet中的所有条目吗?
不可以,您不能清除WeakMap或WeakSet中的所有条目。这些集合没有clear方法,该方法在Map和Set中可用。这是因为WeakMap和WeakSet旨在在键被垃圾回收时自动清理它们的条目。
我可以获取WeakMap或WeakSet的大小吗?
不可以,您无法获取WeakMap或WeakSet的大小。这些集合没有size属性,该属性在Map和Set中可用。这是因为由于垃圾回收,WeakMap或WeakSet的大小可以随时更改。
以上是ES6集合:使用地图,设置,弱图,弱点的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

JavaScript在Web开发中的主要用途包括客户端交互、表单验证和异步通信。1)通过DOM操作实现动态内容更新和用户交互;2)在用户提交数据前进行客户端验证,提高用户体验;3)通过AJAX技术实现与服务器的无刷新通信。

JavaScript在现实世界中的应用包括前端和后端开发。1)通过构建TODO列表应用展示前端应用,涉及DOM操作和事件处理。2)通过Node.js和Express构建RESTfulAPI展示后端应用。

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。 1)C 用于解析JavaScript源码并生成抽象语法树。 2)C 负责生成和执行字节码。 3)C 实现JIT编译器,在运行时优化和编译热点代码,显着提高JavaScript的执行效率。
