ES6键控集合:地图和集合

2020年12月30日11:11:24 发表评论 41 次浏览

本文概述

JavaScript键控集合是数据的结构化集合, 用于存储值并提供用于轻松访问它们的方法。听起来很像数组和对象, 对不对?

实际上, ES6引入了键集合, 以替代数组和对象, 这是JS中到目前为止唯一可用的数据结构。尽管它们足以存储数据, 但是对象和数组还是有一些限制, 并且使用起来有些痛苦。

例如, 要遍历对象或对其进行排序, 必须先将其转换为数组, 然后执行这些操作。对于数组, 循环并不是问题, 但是如果你需要在没有索引的情况下提取特定值, 则根本就不容易。

键控集合-即地图, 组, 弱地图和弱集引入-是为了解决这些问题, 并使使用值或键值对更容易。

在本指南中, 我们将仔细研究映射和集合, 并检查它们的语法, 它们与对象和数组的区别以及它们提供的方法。我们还将比较他们的表现。

JavaScript集

JavaScript集在某种意义上类似于数组, 因为它们也是值的集合。但是, 与数组不同, 这些数据集合只能包含唯一值。换句话说, 你不能在一个集合中有重复项。

数组和集合之间的第二个区别是, 在集合内部, 值没有特定的顺序存储, 因此你可以按它们的名称进行调用。

让我们创建一个新集合以查看其实际效果。你可以在下面的第一个练习中找到示例JSFiddle.

let events = new Set();
let event1 = { type: "concert", day: "Saturday" };
let event2 = { type: "book launch", day: "Wednesday"};
let event3 = { type: "conference", day: "Thursday"};
let event4 = { type: "meet up", day: "Monday" };
// Let's add each event to the set
events.add(event1);
events.add(event2);
events.add(event3);
events.add(event4);

如你所见, 语法非常简单。你使用新的组()方法和使用加()方法以将值推入集合中。

要查看集合包含哪些值, 可以使用values()内部的方法为……的循环。

我们为制作了一个自定义演示.
不完全是。点击这里查看.

ES6键控集合:地图和集合1
for (let item of events.values()) {
  console.log(item);
}

如果要检查是否在集合中找到特定值, 可以使用具有(值)方法。要删除项目, 你可以使用删除(值)方法。

console.log(events.has(event2));

events.delete(event3);
for (let value of events) {
        console.log(value)
}

可用于集合的其他有用方法包括明确()和尺寸()。前者从集合中删除所有项, 而后者返回集合中的元素数。

我们已经确定, 这种类型的集合只能包含唯一值。如果我们想添加一个事件两次, 会发生什么?

let cities = new Set();

let city1 = { name: "London" };
let city2 = { name: "Barcelona"};
let city3 = { name: "Milan"};

cities.add(city1);
cities.add(city2);
cities.add(city1);
cities.add(city3);

cities.forEach((city, cities) => {
  console.log(city);
});

这将列出三个城市的名称, 每个城市仅一次。

如你所见, 集合的语法和方法非常简单且易于使用。但是什么时候以及为什么要使用这种类型的键集合?

设置与数组:用途和性能

如果要执行诸如过滤和从数据集合返回唯一值之类的操作, 则将集转换为数组, 反之亦然, 非常容易。

将集合变成数组的方法如下:

let set = new Set([9, 15, "a string", {"objectKey": "objectValue"}]);
set.add(true);

let arr = [...set]; // destructuring

console.log(arr); fj

// Outputs [9, 15, "a string", {objectKey: "objectValue"}, true]

正如你所看到的, 这次集合包含数据类型的组合:数字, 字符串, 对象和布尔值。为了将此集合转换为数组, 我们使用了重组。

将数组转换为集合的方法如下:

let arr2 = [9, 15, "a string", {"objectKey": "objectValue"}];

let arr2converted = [...new Set(arr2)];

console.log(arr2converted);

// Outputs [9, 15, "a string", {objectKey: "objectValue"}, true]

同样, 你可以在以下位置找到此练习的代码JDFiddle.

现在, 让我们看一个示例, 在该示例中, 数组中有重复的项目, 我们希望将其过滤掉。我们可以通过两种方式做到这一点:

// Method 1

let users = ["John", "Murray", "Jane", "Jane", "Anne"];

function unique(users) {
        return Array.from(new Set(users));
}

console.log(unique(users));

// Method 2

let set = new Set(users);
let arrFromSet = [...set];

console.log(arrFromSet);

此练习的代码可在JSFiddle.

最后, 假设我们要从上方将所有用户添加到新集合和新数组中。让我们看看哪个集合可以更快地执行操作。

let arr = [], set = new Set();
let users = ["John", "Murray", "Jane", "Jane", "Anne", "John", "Murray", "Jane", "Jane", "Anne"];

for (let i = 0; i < users.length; i++) {
  arr.push(users[i]);
  set.add(users[i]);
}

let result;

console.time('Array'); 
result = arr.indexOf("Anne") !== -1; 
console.timeEnd('Array');

console.time('Set'); 
result = set.has("Anne"); 
console.timeEnd('Set');

直接在控制台中运行此代码。结果如下:

Array: 0.013916015625ms
Set: 0.0078125ms

这里的差异很小, 但是设置更快。如果对大数据集执行此类操作, 则后一种收集类型是更好的选择。

JavaScript地图

在需要使用键值对但又需要更多灵活性的情况下, 可以使用地图代替对象。顾名思义, 它们只是用于将键映射到值。

在JavaScript对象中, 该对中的每个键都必须是字符串或符号。但是, 在地图中, 键是不受限制的, 这意味着你可以使用另一个对象, 一个函数甚至一个基本类型作为键。

地图语法如下所示:

let users = [{
    id: 1, name: 'John'
  }, {
    id: 2, name: 'Murray'
  }, {
    id: 3, name: 'Jane'
  }, {
    id: 4, name: 'Jane'
  }, {
    id: 5, name: 'Anne'
  }
]

let userNames = users.map(function(user) {
  console.log(user.name)
});

如果没有这种类型的键集合, 则必须首先创建一个空数组, 然后将所有用户名放入其中。

let userNms = [];

users.forEach(function (user) {
  userNms.push(user.name);
});

console.log(userNms);

这是代码为此练习。

映射使用的方法类似于集合所使用的方法:明确, 删除, 具有, 价值观, 参赛作品, 每次。我们不会全部介绍它们, 但将介绍三种特定于地图的方法:组(), 得到()和entry().

组()将键值对添加到地图对象, 而得到()检索指定键的值。

这是一个例子:

const user1 = new Map();
user1.set('id', 1);
user1.set('name', 'John');

console.log(user1.get('id'));

如果我们想从map集合中获取键值对该怎么办?我们可以使用entry()迭代器的方法。

const user1 = new Map();
user1.set('id', 1);
user1.set('name', 'John');

console.log(user1.get('id'));

let iterator = user1.entries();

console.log(iterator.next().value);
console.log(iterator.next().value);

这是代码.

地图与对象:用途和性能

地图和对象非常相似, 但是主要区别在于, 在地图内部, 任何数据类型都可以是键, 因此你不仅限于字符串。当你要存储与对象相关的数据, 但又由于其局限性而不想将其添加到对象本身或使用对象数组时, 此功能非常有用。

你还可以直接迭代地图的键或值。对于对象, 你首先必须将它们转换为数组, 但这并不总是可行的。以下是地图集合上的迭代示例。

let userIDs = new Map();

let user1 = {name: 'John'}, user2 = {name: 'Murray'}, user3 = {name: 'Jane'};

userIDs.set(user1, 1) .set(user2, 2) .set(user3, 3);

// Method 1

for (let [name, id] of userIDs) {
  console.log(name);
  console.log(id);
}

// Method 2

userIDs.forEach((name, id) => {
  console.log(name);
  console.log(id);
});

这是此示例的代码.

要将对象转换为地图, 我们可以使用Object.entries()方法。

const obj = {
  'name': John, 'id': 1, }

const map = new Map(Object.entries(obj));

console.log(map.get('name')) 
// Outputs John

现在, 让我们将对象与地图进行比较, 看看它们在性能方面的表现。将集合与数组进行比较时, 我们将使用与之前相同的示例。

let obj = {}, map = new Map();

let users = ["John", "Murray", "Jane", "Jane", "Anne", "John", "Murray", "Jane", "Jane", "Anne"];

for (let i = 0; i < users.length; i++) {
  obj[i] = i;
  map.set(i, i);
}

let result;

console.time('Object'); 
result = obj.hasOwnProperty("Anne"); 
console.timeEnd('Object');

console.time('Map'); 
result = map.has("Anne"); 
console.timeEnd('Map');

你可以找到此练习的代码这里.

这两个集合的性能如下。

Object: 0.031982421875ms
Map: 0.0146484375ms

为了进行比较, 数组和集合的性能为:

Array: 0.013916015625ms
Set: 0.0078125ms

如你所见, 尽管映射和集合类似于数组和对象, 但是这些更新的键集合更灵活, 更易于迭代且性能更高。

日志火箭:通过了解上下文更容易调试JavaScript错误

调试代码始终是一项繁琐的任务。但是, 你越了解错误, 就越容易修复它们。

日志火箭使你能够以新颖独特的方式理解这些错误。我们的前端监控解决方案跟踪用户与你的JavaScript前端的互动, 从而使你能够准确找出导致错误的用户行为。

LogRocket仪表板免费试用横幅

notlogy记录控制台日志, 页面加载时间, 堆栈跟踪, 缓慢的网络请求/响应(带有标题+正文), 浏览器元数据和自定义日志。了解你的JavaScript代码的影响再简单不过了!

免费试用

.

一盏木

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: