by Joe Morgan

乔·摩根(Joe Morgan)

不要解决:如何将JavaScript集合与目标相匹配 (Don’t settle: how you can match your JavaScript collection to your goals)

I loved JavaScript even when the world hated it. But I always had a hard time justifying collections. Objects are kind of a key-value store, but not really. And they were horrible if you needed to sort or loop. Arrays were easier to loop over, but clunky if you needed to pull out a specific value without an index.

即使世界讨厌它,我也喜欢JavaScript。 但是我总是很难证明收藏的合理性。 对象是一种键值存储,但实际上不是。 如果您需要排序或循环,它们将很可怕。 数组更容易循环,但是如果您需要在没有索引的情况下提取特定值,则很麻烦。

The sad truth is that most of the time developers would just grab whatever collection popped into their head first. Then torture it with conversions to get whatever they needed.

可悲的事实是,在大多数情况下,开发人员只会抢先出现在他们脑海中的所有收藏。 然后用转换折磨它,以获得所需的一切。

It was painful.

真痛苦

Things are different now. There are more collection types. There are more methods. There are better techniques and even one-line expressions to switch between collection types. Why then does it seem like we are still just guessing when we pick a collection type?

现在情况有所不同。 收集类型更多。 有更多的方法。 有更好的技术,甚至可以使用单行表达式在集合类型之间切换。 为什么然后我们仍在猜测何时选择集合类型呢?

I speak regularly about JavaScript and code quality. I’ve written books about new syntax. But I find that most developers, even experienced ones, don’t put much thought into their collection choice.

我定期谈论JavaScript和代码质量 。 我写过有关新语法的书 。 但是我发现大多数开发人员,即使是经验丰富的开发人员,也都没有在他们的收藏选择中花太多心思。

Time to end that. Not only do we have Arrays and Objects. We also have Maps, Sets, WeakMaps, and WeakSets.

是时候结束了。 我们不仅拥有数组和对象。 我们也有Maps,Sets,WeakMaps和WeakSets。

So which should you choose? Each collection has ups and downs. But in general, there are three big factors that should influence your choice:

那么您应该选择哪一个呢? 每个集合都有起伏。 但总的来说,有三大因素会影响您的选择:

  • Iterable: Can you loop over the collection directly and access each member one at a time?

    可迭代 :您能否直接遍历集合并一次访问每个成员?

  • Keyed: Can you find a value using a special key without worrying about the other collection members?

    键控 :您可以使用特殊键查找值而不必担心其他集合成员吗?

  • Destructurable: Can you pull pieces of the collection into variables quickly and easily?

    可破坏性 :您可以快速轻松地将集合中的各个部分放入变量中吗?

Each collection type is strong in some areas and weak in others. There are other advantages and disadvantages, but these are the big three for most code.

每种收集类型在某些方面都很强,而在其他方面则很弱。 还有其他优点和缺点,但这是大多数代码的三大优点。

数组 (Arrays)

Arrays are probably the most flexible collection. That makes them a great point to start exploring collections.

数组可能是最灵活的集合。 这使他们成为开始探索藏品的好地方。

Here’s a list of my grade school teachers (names changed to protect the innocent).

这是我的小学老师的名单(为了保护无辜者而改名)。

const myTeachers = ['Cooper', 'Simes', 'Butler'];

Arrays preserve order which is great since this is the correct order of my first, second, and third grade teachers. Since the order is meaningful and I happen to know the meaning, I can use destructuring to pull out the items into variables.

数组保留了很好的顺序,因为这是我的一年级,二年级和三年级老师的正确顺序。 由于订单是有意义的,我碰巧知道的意思,我可以用解构的物品拉出到变量。

const [firstGrade, secondGrade, ...others] = myTeachers.

Destructuring is a quick way to pull information out of a collection into separate variables. It can also create subsets of information. The variablefirstGrade has the value ofCooper . The next variable, secondGrade is Simes . The last variable is a little different, using the three dots ... we are saving the rest of the variables, one in this case, as a separate array. That means others is also an array: ['Butler'] . In this case, the ... is a rest pattern. We’re saving the rest of the of values after all.

解构是将信息从集合中提取到单独的变量中的快速方法。 它还可以创建信息的子集。 变量firstGrade的值为Cooper 。 下一个变量secondGradeSimes 。 最后一个变量有些不同,使用三个点...我们将其余的变量(在本例中为一个)保存为单独的数组。 这意味着others也是一个数组: ['Butler'] 。 在这种情况下, ...是休息模式。 毕竟,我们将保存其余的值。

Back to my collection of teachers. Let’s say you don’t care about the order they taught me, you are more interested in an alphabetized list. Now, before you sort the array, remember, sorting is a mutating function, so the action will change the original array. And since the order matters, you don’t want to make a permanent change. Fortunately, it’s not a big problem since you can create a new array with the spread operator: [...myTeachers] .

回到我的老师收藏中。 假设您不在乎他们教我的顺序,而您对按字母顺序排列的列表更感兴趣。 现在,在对数组进行排序之前,请记住,排序是一种变异函数,因此该操作将更改原始数组。 而且由于顺序很重要,因此您不想进行永久更改。 幸运的是,这不是一个大问题,因为您可以使用传播运算符创建一个新数组: [...myTeachers]

The reason you can use the spread operator is that arrays have a built-in iterator which allows you to act on a collection one at a time. In other words, arrays are iterable. The spread operator takes those items and creates a new list one at a time. Putting the whole thing in square brackets creates a new array. The iterable property is also what lets you do nice things like loop using for...of or run a function on each item of the array as you would do with the .map and .reduce methods.

您可以使用散布运算符的原因是数组具有内置的迭代器 这样您就可以一次对一个集合进行操作。 换句话说,数组是可迭代的 。 价差操作员获取这些项并一次创建一个新列表。 将整个内容放在方括号中会创建一个新数组。 可迭代的属性还使您可以像使用.map.reduce方法一样,执行诸如for...of循环或在数组的每个项目上运行函数之类的.reduce

Back to sorting. Now that you can make a new array, you don’t have to worry about the mutations. The sort function is a one-liner.

返回排序。 现在您可以制作一个新的阵列,您不必担心突变。 排序功能是单线的。

const sortedTeachers = [...myTeachers].sort();

Since arrays are destructurable and iterable, you can pull out information easily or access each item one at a time. Seems pretty great, right? Of course, arrays are not perfect. Suppose you didn’t know the order of the array, but you did want my second-grade teacher. Now you have a problem. Since arrays are not keyed, you can’t just pull out the information you need. The best you could do is create a complicated array of pairs — an array containing two items — along with an array method to find the one you want.

由于数组是可破坏和可迭代的,因此您可以轻松提取信息或一次访问每个项目。 看起来还不错吧? 当然,数组不是完美的。 假设您不知道数组的顺序,但是您确实想要我的二年级老师。 现在你有问题了。 由于数组没有键控,因此您不能仅仅提取所需的信息。 最好的办法是创建一个复杂的成对数组-包含两个项目的数组-以及找到所需数组的数组方法。

export const myTeacherPairs = [['first', 'Cooper'], ['second', 'Simes'], ['third', 'Butler']];
return teachers.find(teacherPair => teacherPair[0] === 'second');

This is a little clunky. An array of pairs is super important and you’ll see more of them later, but this is a pretty inefficient way to handle data lookups.

这有点笨拙。 成对的阵列非常重要,稍后您将看到更多对,但这对处理数据查找而言是一种非常低效的方法。

The problems are that the collection is not keyed. Arrays are good at lots of things, but key-value stores are not one. So you’re in a bind. You like the destructuring properties and the iterables. But retrieving key-value information is not simple. This is usually when developers turn to objects. But before that here’s a summary of arrays:

问题在于该集合未设置密钥 。 数组在很多方面都很擅长,但是键值存储却不是一个。 所以你陷入困境。 您喜欢解构属性和可迭代对象。 但是,检索键值信息并不简单。 通常是在开发人员转向对象时。 但在此之前,这里是数组的摘要:

✅ Destructurable

✅可破坏的

✅ Iterable

er可迭代

❌ Keyed

ed键控

对象 (Objects)

Most JavaScript developers instinctively reach for an object as soon as they need to store key-value pairs. Objects in JavaScript can get pretty complex. For the sake of this example, think of them as a simple way to pass data around. No functions. No this keyword. Just key-value pairs.

大多数JavaScript开发人员本能地在需要存储键值对时就到达对象。 JavaScript中的对象可能变得非常复杂。 对于本示例,请将它们视为传递数据的简单方法。 没有功能。 没有this关键字。 只是键值对。

Start off by rewriting my array of teachers into an object:

首先将我的教师数组重写为一个对象:

const teachers = {  first: "Cooper",  second: "Simes",  third: "Butler",};

If you needed to find just my second-grade teacher and didn’t care about the other parts of the object, you can pull it out directly: teachers.second . Even better, you can pull the value directly into a variable with destructuring. It’s a simple assignment as long as the variable matches the object key.

如果您只需要查找我的二年级老师,而不关心对象的其他部分,则可以直接将其拉出: teachers.second 。 更好的是,您可以通过解构将值直接拉到变量中。 只要变量与对象键匹配,这就是一个简单的赋值。

const { second } = teachers;

Destructuring is probably the biggest reason to use objects when passing around data. You can easily collect multiple values in an object and then pass it to another function where you can pull the information out again.

在传递数据时,解构可能是使用对象的最大原因。 您可以轻松地在一个对象中收集多个值,然后将其传递给另一个函数,在该函数中您可以再次提取信息。

function getSecondGradeInfo({ second }) {  const school = "Lakin";  return {    school,    teacher: second  }}

Things start to fall apart when you want to iterate over the object. You either have to convert some part of the object to an array or you have to use a for...in loop.

当您要遍历对象时,事情开始崩溃。 您必须将对象的某些部分转换为数组,或者必须使用for...in循环。

Object.keys(teachers).map(grade => `${grade}:${teachers[grade]}`).join(' ');
let myTeacher = '';for(const grade in teachers) {  myTeacher += ` ${grade}:${teachers[grade]}`;}

Things are getting a little messy already. You either have to iterate over keys or you have to mutate a variable. Worse still, objects don’t guarantee order. You can never trust your for...in loop to give the results in the sequence you want.

事情已经变得有些混乱了。 您要么必须遍历键,要么必须变异一个变量。 更糟糕的是,对象不能保证顺序。 您永远不会信任for...in循环以所需的顺序给出结果。

All of these problems come from an object’s lack of an iterable property. Object.keys and for...in both use the iterator that comes from converting keys to an array.

所有这些问题都来自对象缺乏可迭代的属性。 Object.keysfor...in两个都使用将键转换为数组的迭代器。

Beyond that, there are other problems with objects. There are limited key options. You can’t use numbers as keys, for example. They aren’t as performant as other collections. But for the most part, they are good for passing data around without a lot of loops.

除此之外,对象还有其他问题。 关键选项有限。 例如,您不能将数字用作键。 它们的表现不如其他系列。 但是在大多数情况下,它们非常适合传递数据而不会产生很多循环。

To summarize:

总结一下:

✅ Destructurable

✅可破坏的

❌ Iterable

er可迭代

✅ Keyed

ed键控

地图 (Maps)

Maps are a new collection type for JavaScript. They are a proper key-value store. Which is just a way of saying they were designed specifically for that purpose. Unlike objects, you still have to explicitly create a new instance:

地图是JavaScript的新集合类型。 它们是适当的键值存储。 这只是说它们是专门为此目的而设计的。 与对象不同,您仍然必须显式创建一个新实例:

const teachers = new Map();

After that, you set each item by passing a key then a value as arguments.

之后,通过传递键和值作为参数来设置每个项目。

teachers.set('first', 'Cooper').set('second', 'Simes').set('third', 'Butler);

To retrieve a value, you call the get() method along with the key name.

要检索值,请调用get()方法以及键名。

teachers.get('second'); // Simes

This might look a little familiar already. It’s not much different thanlocalStorage.setItem(key, value which you may have used to store data between visits to a webApp.

这可能看起来有点熟悉。 它与localStorage.setItem(key, value没什么不同,您可以在两次访问WebApp之间使用该localStorage.setItem(key, value存储数据。

As key-value stores, maps are pretty great. They take a wider variety of keys. And while an objects lookup time is linear, a Map’s lookup time will be logarithmic.

作为键值存储,地图非常棒。 他们采用了各种各样的钥匙 。 虽然对象的查找时间是线性的,但地图的查找时间将是对数的 。

But the biggest advantage is that they have a built-in iterable. That means you can do things like access key-value pairs directly:

但是最大的优点是它们具有内置的可迭代性。 这意味着您可以执行诸如直接访问键值对之类的操作:

let myTeachers = '';for([grade, name] of teachers) {  myTeachers += ` ${grade}:${name}`;}

A few things to say about that. It may look like you are destructuring the map at the start of the for loop. You actually aren’t. When you iterate over a map, you get back a pair with the key and the value. So you’re actually destructuring an array.

关于此事有几点要说。 好像您在for循环的开始处正在销毁地图。 你实际上不是。 遍历地图时,您将获得一个包含键和值的对。 因此,您实际上是在破坏数组。

Next, you may notice that you’re still mutating a variable. That’s not so great. Fortunately, since a map is an iterable, you can use the spread operator to convert the map to an array of pairs. That means

接下来,您可能会注意到您仍在对变量进行突变。 那不是很好。 幸运的是,由于映射是可迭代的,因此可以使用传播运算符将映射转换为成对的数组。 那意味着

[...teachers]

will become

会变成

[  ['first', 'Cooper'],  ['second', 'Simes'],  ['third', 'Butler'],]

With the map converted to an array, you can now map the items to create your string.

将映射转换为数组后,您现在可以映射项目以创建您的字符串。

[...teachers].map(([grade, name]) => `${grade}:${name}`).join();

That means that you have access to all the array methods in three short characters.

这意味着您可以使用三个短字符访问所有数组方法。

Oh, and since it’s iterable, the order is preserved. If you add your first-grade teacher at the beginning, you’ll get it at the beginning.

哦,由于它是可迭代的,因此顺序得以保留。 如果您在一开始就添加了一年级老师,那么一开始就会得到它。

So what are the disadvantages? The biggest is the lack of direct destructuring. You can’t pull a value out without either calling the get()method or by converting to an array. That means passing data between functions gets a little wordier. You also can’t represent maps as a JSON string. So you won’t pull maps from an API anytime soon.

那有什么缺点呢? 最大的是缺乏直接的结构调整。 您必须先调用get()方法或将其转换为数组,才能提取出一个值。 这意味着在函数之间传递数据会有点麻烦。 您也不能将地图表示为JSON字符串。 因此,您不会很快就从API中提取地图。

Still, if you have data that you know you’ll want to loop over while still retaining the ability to pull data quickly with a key, maps are your best best.

不过,如果您知道自己想要循环使用的数据,但仍然保留使用键快速提取数据的能力,则地图是最好的选择。

To summarize:

总结一下:

❌ Destructurable

❌可破坏的

✅ Iterable

er可迭代

✅ Keyed

ed键控

在之间移动 (Moving Between)

You probably noticed one frustrating pattern. There’s no one collection that can do it all.

您可能会注意到一种令人沮丧的模式。 没有一个集合可以做到这一切。

Fortunately, that’s not as big of a problem as you may think.

幸运的是,这并没有您想象的那么大。

You’ve already seen that you can convert a map to an array with the spread operator. You can also go the other way and convert an array to the map, by passing it into the constructor.

您已经看到可以使用传播运算符将映射转换为数组。 您也可以采用另一种方法,将数组传递给构造函数,以将数组转换为地图。

You can also speed up the initial creation process by passing an array of pairs:

您还可以通过传递成对的数组来加快初始创建过程:

const myTeachers = [  ['first', 'Cooper'],  ['second', 'Simes'],  ['third', 'Butler'],]const teachers = new Map(myTeachers);

At this point, when you have a map, you essentially have access to both the properties of an array and the properties of a map with only a slight conversion.

在这一点上,当您有一个地图时,您只需稍加转换就可以访问数组的属性和地图的属性。

Objects are getting better. With Object.entries() you can create an array of pairs from an object.

对象越来越好。 使用Object.entries()可以从一个对象创建一个成对数组。

const teachers = {  first: "Cooper",  second: "Simes",  third: "Butler",};
const myTeachers = Object.entries(teachers);
myTeachers[0]// ['first', 'Cooper']

That means when you have an object, you have access to array methods with a simple conversion. Going back, though, is a little harder. There’s currently a proposal for Object.fromEntries() that will take an array of pairs and create an object. But that’s still a little bit away.

这意味着当您有一个对象时,您可以通过简单的转换访问数组方法。 但是,回去要困难一些。 当前有一个针对Object.fromEntries()的建议 ,它将采用成对的数组并创建一个对象。 但这还差一点。

However, once it’s here, you won’t be locked into any particular collection type. And that’s the best news of all. Once you can move easily and quickly between collections, you can start to leverage the best features of each. Destructuring values when it’s convenient, iterating when you need to.

但是,一旦它在这里,您就不会被锁定在任何特定的集合类型中。 这是所有方面最好的消息。 一旦可以轻松快速地在各个收藏夹之间移动,就可以开始利用每个收藏夹的最佳功能。 在方便时分解值,并在需要时进行迭代。

In other words, you can look at the data you have and the code you need and pick the appropriate collection type. If another function needs a different type, write a simple conversion. No more guessing. No more frustrations. You can match your collection to your goals not your code to your collection.

换句话说,您可以查看您拥有的数据和所需的代码,然后选择适当的收集类型。 如果另一个函数需要其他类型,则编写一个简单的转换。 没有更多的猜测。 没有更多的挫败感。 您可以将集合与目标相匹配,而不是将代码与集合相匹配。

翻译自: https://www.freecodecamp.org/news/dont-settle-how-you-can-match-your-javascript-collection-to-your-goals-c94cb994be4e/

不要解决:如何将JavaScript集合与目标相匹配相关推荐

  1. SaaS企业如何构建与自身增长目标相匹配的组织力?

    2020年的疫情,迅速提高的数字化渗透率,SaaS行业迎来红利期.然而,两年之后的今天,不少企业猛然发现,营收增长的背后不是盈利的增长,而是亏损的加剧. 本以为从几年前产品力的角逐中脱颖之后就稳了,没 ...

  2. SaaS企业如何构建与自身增长目标相匹配的市场力?

    "优秀的公司是满足需求,而伟大的公司是创造市场".传统的思维是囿于现有市场被动接受竞争,而创新的思维是跳出现有市场主动寻找机会. 当数据已经成为企业最核心的生产要素,SaaS作为企 ...

  3. Python语言学习:解决python版本升级问题集合(python2系列→Python3系列)导致错误的总结集合

    Python语言学习:解决python版本升级问题集合(python2系列→Python3系列)导致错误的总结集合 目录 Python版本升级的原因 Text and binary data in P ...

  4. 解决Tomcat下源服务器未能找到目标资源的表示或者是不愿公开一个已经存在的资源表示

    解决Tomcat下源服务器未能找到目标资源的表示或者是不愿公开一个已经存在的资源表示 源服务器未能找到目标资源的表示或者是不愿公开一个已经存在的资源表示 笔者报错时的运行环境: JDK 13.0.2 ...

  5. emlog通过pjax实现无刷新加载网页--完美解决cnzz统计和javascript失效问题

    想要更详细了解pjax,需要查看官网 或者看本站文章:jQuery.pjax.js:使用AJAX和pushState无刷新加载网页(官网教程中文翻译) 效果看本站,音乐无刷新播放,代码高亮和复制js加 ...

  6. python opencv模板匹配多目标_基于opencv的多目标模板匹配

    利用opencv进行多目标模板匹配,只要是利用其matchTemplate函数,但在多目标(这里是讨论目标图片中不同大小模板的匹配),以下贴出代码和图片,供大家参考: #include #includ ...

  7. 数据库:数据查询(指定的列、全部列、经过计算的值、消除重复的行、查询满足条件的元组、比较查询、范围查询、集合查询、字符匹配查询)

    数据查询是数据库的核心操作,SQL提供了 select 语句实现查询功能 1.查询指定的列 格式: select 查询列表,查询列表 from 查询的表名 2.查询全部列(查询的顺序不同) (1) s ...

  8. 豆瓣刮削器无法连接远程服务器,如何解决kodi播放器电影刮削器匹配失败的问题?...

    原标题:如何解决kodi播放器电影刮削器匹配失败的问题? 我们在上一篇文章中介绍了KODI的下载.安装.设置中文界面的过程(如何用kodi搭建一个私人影院?手把手教你搭建kodi播放器.),同时也讲到 ...

  9. pytorch错误解决 | 错误‘Widget Javascript not detected. It may not be installed or enabled properly.‘

    错误'Widget Javascript not detected. It may not be installed or enabled properly.' 当在进行如下代码时, import t ...

最新文章

  1. 公司项目NODEJS实践0.3[ mongo / session ...]
  2. 皮一皮:你更想成为哪个身材...
  3. Linux 获取设备树源文件(DTS)里描述的资源
  4. python3.8图片_python3.8.3官方中文文档[PDF][CHM][31.14MB]
  5. 突出重围:Oracle 10.2.0.5应用SCN补丁解决DB Link预警实践
  6. 语料库python_NLPPython笔记——语料库
  7. 电脑控制android 源代码,[源代码]电脑通过adb控制安卓手机
  8. 如何将svg格式图片转换为其他格式图片,如png
  9. 基础实验 7-2.1 魔法优惠券(25 分)
  10. 祭奠信任Nokia的那些日子
  11. 基于高通410c开发板,开发android端家庭控制中心APP(1)
  12. 带你一起Piu Piu Piu
  13. U-Boot1.2.0移植YC2440
  14. lodop 打印说明
  15. 仿爱奇艺视频,腾讯视频,搜狐视频首页推荐位轮播图介绍(一)
  16. 2022新PHP赞/易支付系统源码+全新UI界面
  17. 用图记忆C语言中的运算符优先级
  18. 基于Web的美食分享平台的设计与实现——HTML+CSS+JavaScript水果介绍网页设计(橙子之家)
  19. 进入信息爆炸时代,大数据产业应运而生
  20. 门诊电子处方软件V12.1

热门文章

  1. django-模型类管理器-create方法-models属性
  2. 使用DataGrip连接Hive
  3. [大数据行业应用发展前景分析] 阿里潘永花报告:大数据产业将成为新的煤和石油介绍...
  4. PHP规范之PSR-1
  5. Redhat Enterprise 6 下安装Oracle 11g报错
  6. U盘拒绝访问怎么办 快速方法解决U盘问题
  7. php中常见的header类型
  8. 计算机达人成长之路 目录
  9. Hello Android
  10. 拒绝网络*** 如何防御Sniffer***