资讯专栏INFORMATION COLUMN

细说es6中的Set和Map

Ryan_Li / 600人阅读

摘要:返回一个布尔值,表示该值是否为的成员。返回键名的遍历器返回键值的遍历器返回键值对的遍历器使用回调函数遍历每个成员需要特别指出的是,的遍历顺序就是插入顺序。该数组的所有成员,都会自动成为实例对象的成员。这意味着,数组的成员只能是对象。

1.Set

ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set 本身是一个构造函数,用来生成 Set 数据结构。
基本用法:
const set = new Set();
set函数可以接受一个数组(或者具有iterable 接口的其他数据结构)作为参数,用来初始化:
const set = new Set(["1","2","3","2"]); //注意:set结构不会接受重复的参数,这也体现了set结构去重的方法

扩展运算符: ... //可以把set数据结构转化为数组类型
例如:
[...set]
另一种方法是利用Array.from()方法:
const set = new Set(["1","2","3"]);
例如: Array.from(set)
在set结构中,两个对象总是不相等的,NaN也等于其本身。

下面是set结构的属性和方法:
Set 结构的实例有以下属性:
Set.prototype.constructor:构造函数,默认就是Set函数。
Set.prototype.size:返回Set实例的成员总数。

Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。下面先介绍四个操作方法。
add(value):添加某个值,返回 Set 结构本身。
delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
has(value):返回一个布尔值,表示该值是否为Set的成员。
clear():清除所有成员,没有返回值。
例如:
set.add(10) //向set添加一个成员
set.delete(10) //删除set一个成员
set.has(10) //检测这个值是否存在,返回布尔值true或false
set.clear() //清除所有set成员,没有返回值

遍历操作
Set 结构的实例有四个遍历方法,可以用于遍历成员。

keys():返回键名的遍历器
values():返回键值的遍历器
entries():返回键值对的遍历器
forEach():使用回调函数遍历每个成员
需要特别指出的是,Set的遍历顺序就是插入顺序。这个特性有时非常有用,比如使用 Set 保存一个回调函数列表,调用时就能保证按照添加顺序调用。

(1)keys(),values(),entries()
keys方法、values方法、entries方法返回的都是遍历器对象(详见《Iterator 对象》一章)。由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。

2.WeakSet

含义:
WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。
(1),WeakSet 的成员只能是对象,而不能是其他类型的值。
WeakSet 适合临时存放一组对象
WeakSet 的成员是不适合引用的,因为它会随时消失。另外,由于 WeakSet 内部有多少个成员,取决于垃圾回收机制有没有运行,运行前后很可能成员个数是不一样的,而垃圾回收机制何时运行是不可预测的,因此 ES6 规定 WeakSet 不可遍历。
作为构造函数,WeakSet 可以接受一个数组或类似数组的对象作为参数。(实际上,任何具有 Iterable 接口的对象,都可以作为 WeakSet 的参数。)该数组的所有成员,都会自动成为 WeakSet 实例对象的成员。
注意,是a数组的成员成为 WeakSet 的成员,而不是a数组本身。这意味着,数组的成员只能是对象。

WeakSet 结构有以下三个方法。
WeakSet.prototype.add(value):向 WeakSet 实例添加一个新成员。
WeakSet.prototype.delete(value):清除 WeakSet 实例的指定成员。
WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在 WeakSet 实例之中。

const ws = new WeakSet();
const obj = {};
const foo = {};

ws.add(window);
ws.add(obj);

ws.has(window); // true
ws.has(foo); // false

ws.delete(window);
ws.has(window); // false

另外:WeakSet 没有size属性,没有办法遍历它的成员。

3.Map

含义和基本用法
JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。
为了解决这个问题,ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。
例如:
const m = new Map();
const o = {p: "Hello World"};

m.set(o, "content")
m.get(o) // "content"

m.has(o) // true
m.delete(o) // true
m.has(o) // false
事实上,不仅仅是数组,任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构(详见《Iterator》一章)都可以当作Map构造函数的参数。这就是说,Set和Map都可以用来生成新的 Map。

实例的属性和操作方法

(1)size 属性

size属性返回 Map 结构的成员总数。

const map = new Map();
map.set("foo", true);
map.set("bar", false);

map.size // 2
(2)set(key, value)

set方法设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。

const m = new Map();

m.set("edition", 6) // 键是字符串
m.set(262, "standard") // 键是数值
m.set(undefined, "nah") // 键是 undefined
set方法返回的是当前的Map对象,因此可以采用链式写法。

let map = new Map()
.set(1, "a")
.set(2, "b")
.set(3, "c");
(3)get(key)

get方法读取key对应的键值,如果找不到key,返回undefined。

const m = new Map();

const hello = function() {console.log("hello");};
m.set(hello, "Hello ES6!") // 键是函数

m.get(hello) // Hello ES6!
(4)has(key)

has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。

const m = new Map();

m.set("edition", 6);
m.set(262, "standard");
m.set(undefined, "nah");

m.has("edition") // true
m.has("years") // false
m.has(262) // true
m.has(undefined) // true
(5)delete(key)

delete方法删除某个键,返回true。如果删除失败,返回false。

const m = new Map();
m.set(undefined, "nah");
m.has(undefined) // true

m.delete(undefined)
m.has(undefined) // false
(6)clear()

clear方法清除所有成员,没有返回值。

let map = new Map();
map.set("foo", true);
map.set("bar", false);

map.size // 2
map.clear()
map.size // 0

遍历方法

Map 结构原生提供三个遍历器生成函数和一个遍历方法。

keys():返回键名的遍历器。
values():返回键值的遍历器。
entries():返回所有成员的遍历器。
forEach():遍历 Map 的所有成员。
需要特别注意的是,Map 的遍历顺序就是插入顺序。

4.WeakMap

WeakMap结构与Map结构类似,也是用于生成键值对的集合。
WeakMap与Map的区别有两点。

首先,WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名。
其次,WeakMap的键名所指向的对象,不计入垃圾回收机制。

WeakMap的设计目的在于,有时我们想在某个对象上面存放一些数据,但是这会形成对于这个对象的引用。请看下面的例子。

const e1 = document.getElementById("foo");
const e2 = document.getElementById("bar");
const arr = [
[e1, "foo 元素"],
[e2, "bar 元素"],
];
基本上,如果你要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用 WeakMap。一个典型应用场景是,在网页的 DOM 元素上添加数据,就可以使用WeakMap结构。当该 DOM 元素被清除,其所对应的WeakMap记录就会自动被移除。

const wm = new WeakMap();

const element = document.getElementById("example");

wm.set(element, "some information");
wm.get(element) // "some information"
上面代码中,先新建一个 Weakmap 实例。然后,将一个 DOM 节点作为键名存入该实例,并将一些附加信息作为键值,一起存放在 WeakMap 里面。这时,WeakMap 里面对element的引用就是弱引用,不会被计入垃圾回收机制。
总之,WeakMap的专用场合就是,它的键所对应的对象,可能会在将来消失。WeakMap结构有助于防止内存泄漏。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/108251.html

相关文章

  • 「干货」细说 Array 的常用操作(ES5 ES6)

    摘要:今天,会更具体地将数组的常用操作进行归纳和汇总,以便备不时之需。在公用库中,一般会这么做的判断新增的操作和传入一个回调函数,找到数组中符合当前搜索规则的第一个元素,返回这个元素,并且终止搜索。 showImg(https://segmentfault.com/img/bVbpzuS?w=750&h=422); 前言 上一篇文章「前端面试题系列8」数组去重(10 种浓缩版) 中提到了不少...

    VincentFF 评论0 收藏0
  • 细说es6中的数组

    摘要:函数运行后,返回一个遍历器对象,因此也可以使用扩展运算符。总是返回参数值组成的数组。方法的回调函数可以接受三个参数,依次为当前的值当前的位置和原数组。上面代码中,的参数为,表示要拉平两层的嵌套数组。 1.扩展运算符 含义扩展运算符(spread)是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。console.log(...[1, 2, 3])//...

    Near_Li 评论0 收藏0
  • 细说数组常用遍历的方法

    摘要:需要返回值,如果不给,默认返回使用场景假定有一个数值数组将数组中的值以双倍的形式放到数组写法方法使用场景假定有一个对象数组将数中对象某个属性的值存储到数组中三从数组中找出所有符合指定条件的元素检测数值元素,并返回符合条件所有元素的数组。 showImg(https://segmentfault.com/img/remote/1460000016810336?w=1149&h=524);...

    阿罗 评论0 收藏0
  • 细说数组常用遍历的方法

    摘要:需要返回值,如果不给,默认返回使用场景假定有一个数值数组将数组中的值以双倍的形式放到数组写法方法使用场景假定有一个对象数组将数中对象某个属性的值存储到数组中三从数组中找出所有符合指定条件的元素检测数值元素,并返回符合条件所有元素的数组。 showImg(https://segmentfault.com/img/remote/1460000016810336?w=1149&h=524);...

    AlphaWatch 评论0 收藏0
  • 细说数组常用遍历的方法

    摘要:需要返回值,如果不给,默认返回使用场景假定有一个数值数组将数组中的值以双倍的形式放到数组写法方法使用场景假定有一个对象数组将数中对象某个属性的值存储到数组中三从数组中找出所有符合指定条件的元素检测数值元素,并返回符合条件所有元素的数组。 showImg(https://segmentfault.com/img/remote/1460000016810336?w=1149&h=524);...

    ?xiaoxiao, 评论0 收藏0

发表评论

0条评论

Ryan_Li

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<