键控集合

您可以使用对象字面量来存储键值对,并使用数组来存储值的可迭代集合。ES6 还引入了专门的数据结构来适应更精细的用例:用于键值对的 Map 和用于单个值的 Set。

Map

Map 是一种可迭代的数据结构,用于将信息存储为键值对,类似于对象字面量。与对象字面量不同,Map 允许值和键都具有任何数据类型,并且在迭代 Map 时,会保留元素添加到 Map 的顺序。

要创建 Map,请使用 Map() 构造函数

const myMap = new Map();

myMap;
> Map(0)

您可以使用类似于数组(或任何迭代器对象)的语法预先填充 Map,该语法包含由两个元素组成的类似数组的对象。这些双元素数据结构中的第一个元素将成为键,而第二个元素将成为与该键关联的值。最简单的形式实际上是一个数组,其中每个元素本身都是一个由两个元素组成的数组,即要添加到 Map 的元素的键和值

const myMap = new Map([
    [ "myKey", "A string value" ],
    [ "mySecondKey", 500 ],
    [ "myThirdKey", true ]
]);

myMap;
> Map(3) {'myKey' => 'A string value', 'mySecondKey' => 500, 'myThirdKey' => true}

同样,Map 对象与对象字面量的不同之处在于,值和键都可以采用任何数据类型和值

const notAFunction = () => console.log( "function" );
const myMap = new Map([
  [ null, 0 ],
  [ false, "This is false" ],
  [ undefined, "No defined value" ],
  [ NaN, "Not a number" ]
]);

myMap;
> Map(4) {null => 0, false => 'This is false', undefined => 'No defined value', NaN => 'Not a number'}

要获取、设置或删除 Map 元素,请使用从 Map 构造函数继承的方法

const myMap = new Map();

myMap;
> Map(0)

myMap.set( "myKey", "My value." );

myMap.has( "myKey" );
> true

myMap.get( "myKey" );
"My value."

myMap.delete( "myKey" );

myMap;
> Map(0)

Map 中的键是唯一的,这意味着设置相同的键会覆盖先前存储的键值对

const myMap = new Map([ [ "myKey", "A string value" ] ]);

myMap.set( "myKey", 500 );

myMap;
> Map(1) {'myKey' => 500}

与对象一样,您可以将 Map 分配给使用 const 声明的变量,然后修改该 Map。但是,与其他 const 用例一样,您无法更改或删除变量本身

const myMap = new Map();
myMap.set( "myKey", "A string value" );

myMap;
> Map(1) {'myKey' => 500}

WeakMap

WeakMap 是一种保存“弱”引用的 Map,这些引用必须是对未添加到全局符号注册表中的对象或符号的引用。

要创建 WeakMap,请使用 WeakMap() 构造函数

const myWeakMap = new WeakMap();

myWeakMap;
> WeakMap(0)

WeakMap 语法类似于 Map,但 WeakMap 不可迭代,并且尝试使用对象或符号以外的任何值作为键都会导致语法错误。当 WeakMap 外部不存在对键的引用时,该对象或符号以及 WeakMap 中的关联值都有资格进行垃圾回收

这允许用于诸如在 WeakMap 中存储与对象关联的元数据之类的用例,使用对对象的引用作为键。如果不存在对此对象的其他引用,并且该对象已从内存中删除,则关联的元数据也会被删除。

Set

Set 是唯一值的可迭代集合,有点类似于数组,尽管 Set 只能包含唯一值。与 Map 一样,迭代 Set 会保留元素添加到 Set 的顺序。

要创建 Set,请使用 Set() 构造函数

const mySet = new Set();

mySet;
> Set []

您还可以从数组字面量创建 Set

const mySet = new Set([ 1, 2, 3 ]);

mySet;
> Set(3) [ 1, 2, 3 ]

由于 Set 不允许重复元素,因此当从包含同一值的多个实例的数组创建 Set 时,它仅保留该值的第一个实例

const mySet = new Set([ 1, 2, 3, 2 ]);

mySet;
> Set(3) [ 1, 2, 3 ]

要从 Set 添加或删除元素,请使用从 Set 构造函数继承的方法。这些方法基于元素自身的值而不是引用索引来对元素进行操作

const mySet = new Set();

mySet.add( "My value." );

mySet;
> Set [ "My value." ]

mySet.has( "My value." );
> true

mySet.delete( "My value." );

mySet;
> Set []

尽管 Set 不是索引集合,并且不打算用作索引集合,但 Set 中的元素会按照插入顺序进行迭代。尝试向 Set 添加重复元素值将被跳过,从而保留原始插入顺序

const mySet = new Set([ 1, 2, 3 ]);

mySet;
> Set(3) [ 1, 2, 3 ]

mySet.add( 2 );
> Set(3) [ 1, 2, 3 ]

要从 Set 创建数组,请使用 Array.from() 方法或展开语法

const mySet = new Set([ 1, 2, 3 ]);
const myArray = Array.from( mySet );

myArray;
> Array(3) [ 1, 2, 3 ]

[ ...mySet ];
> Array(3) [ 1, 2, 3 ]

WeakSet

WeakSet 是一个仅包含可垃圾回收值(例如对对象的引用或未添加到全局符号注册表中的符号)的 Set。

要创建 WeakSet,请使用 WeakSet() 构造函数

const myWeakSet = new WeakSet();

myWeakSet;
> WeakSet []

WeakSet 语法类似于 Set,尽管 WeakSet 不可迭代,并且尝试添加对象或符号以外的任何值都会导致语法错误。与 WeakMap 一样,当不存在对 WeakSet 引用的值的其他引用时,该值将有资格进行垃圾回收

这允许用于诸如聚合相关的对象的单个可迭代集合之类的用例。如果不存在对 WeakSet 引用的对象的其他引用,则关联的元素也会从 WeakSet 中删除。

检查您的理解情况

给定以下内容

        const myMap = new Map([ [ "myKey", "My string" ] ]);
        myMap.set( "myKey", 100 );
      

myMap 返回什么?

100
“My string”
未定义