ES6中新的数据容器技术——的Map与Set

822 阅读6分钟

一、Map

特性和定义

ES6 的 Map 类型是键值对的有序列表,而键和值都可以是任意类型(因为它键使用的比较方法也是Object.is()方法)。而Object的key都会被自动的转换为字符串类型,所以 1和 ‘1’是同一个键。

  • Map的创建和使用

Map类型的创建也是使用new Map方法进行创建。 可以使用set()方法传入key和value参数值进行添加每一项数据,使用get()方法传入key获取当前项数据。 如:

  let myMap = new Map();
  myMap.set(1, 'one');
  myMap.set('1', 'one1');
  console.log(myMap); // Map(2) { 1 => 'one', '1' => 'one1' }
  console.log(myMap.get(1)); // one
  console.log(myMap.get(2)); // undefined 
  因为没有2这个key所以获取值undefined

因为Map的key可以是任何数据类型,所以我们还可以将{}作为key,又因为key是使用Object.is()方法进行比较的,所以可以可以存在多个{}创建的数据项。 如:

    let myMap = new Map(),
        key1 = {},
        key2 = {}
    myMap.set(key1, 'one11111');
    myMap.set(key2, 'one22222');
    console.log(myMap.get(key1)); // one11111
    console.log(myMap.get(key2)); // one22222

另一种初始化创建Map的方法是也可以传入一个数组,该数 组中的每一项也必须是数组,内部数组的首个项会作为键,第二项则为对应值。 并且Map 与 Set 共享了以下三个方法,在 Map 与 Set 上都存在: has(key) :判断指定的键是否存在于 Map 中; delete(key) :移除 Map 中的键以及对应的值; clear() :移除 Map 中所有的键与值。 如:

    let myMap = new Map([["name", "xiaoming"], ["age", 25]]);
    console.log(myMap.has("name")); // true
    console.log(myMap.get("name")); // "xiaoming"
    console.log(myMap.has("age")); // true
    console.log(myMap.get("age")); // 25
    console.log(myMap.size); // 2

    myMap.delete("name");
    console.log(myMap.has("name")); // false
    console.log(myMap.size); // 1
    console.log(myMap.has("age")); // true
    console.log(myMap.get("age")); // 25

    myMap.clear();
    console.log(myMap.has("age")); // false
    console.log(myMap.get("age")); // undefined
    console.log(myMap.size); // 0

Map 上的 forEach 方法

Map 的 forEach() 方法类似于 Set 与数组的同名方法,它接受一个能接收三个参数的回调函 数:

  1. Map 中下个位置的值;
  2. 该值所对应的键;
  3. 目标 Map 自身。
    如:
    let myMap = new Map([["name", "xiaoming"], ["age", 25]]);
    myMap.forEach(function(value, key, self) {
        console.log(key + " " + value);
        console.log(self === myMap);
    });

    // 打印
    // name xiaoming
    // true
    // age 25
    // true
  • Map含义和基本用法 JavaScript对象object本质上是键值对的集合,Hash结构。

缺陷是只能使用字符串作为键。

而map结构优化了这个缺陷,它提供了值-值对的形式,让键名不再局限于字符串,是一种更完整的Hash结构实现

可以接受一个数组作为参数,或者任何具有Iterator接口且每个成员都是一个双元素数组的数据结构都可以当作Map的构造函数的参数。

//set对象和map对象都可以以构造函数的形式生成一个新的map结构
const map =new Map()
const map =new Set()
//数组作为参数
const map =new Map([['name','rowland'],['type','1']])
实例的属性和操作方法
Map.prototype.constructor:构造函数,默认就是Map函数。
Map.prototype.size:返回Map实例的成员总数。
Map.prototype.set(key, value):添加某个值,返回 Map结构本身。
Map.prototype.get(key):get方法读取key对应的键值,如果找不到key,返回undefinedMap.prototype.delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
Map.prototype.has(value):返回一个布尔值,表示该值是否为Map的成员。
Map.prototype.clear():清除所有成员,没有返回值。

二、 Set

特性和定义

Set它是一种有序列表并且它的值没有重复。

创建 Set 并添加项目

Set 使用 new Set() 来创建,如果想要往Set中添加值可以使用add()方法进行添加。查看Set中有多少项值,使用 size 属性 。如:

    let mySet = new Set();
    mySet.add(1);
    mySet.add("1");
    console.log(mySet.size); // 2
    console.log(mySet) // Set(2) {1, "1"}

上述代码创建了mySet并且向其中添加了两个参数(1,’1’),并分别打印他们的值。由于Set 不会使用强制类型转换来判断值是否重复(内部使用了Object.is()方法来判断两个值是否相同),所以它们都是独立的值。因此我们还可以往里添加两个对象,并且后面的值不会被忽略(因为使用Object.is()方法比较)。如:

let mySet = new Set();
    mySet.add({});
    mySet.add({});
    console.log(mySet.size); // 2
    console.log(mySet) // Set(2) { {}, {} }

如果 add() 方法添加了两次相同的值,那么在第一次添加之后实际上后面的就会被忽略。如:

    let mySet = new Set();
    mySet.add('a');
    mySet.add('a');
    console.log(mySet.size); // 1
    console.log(mySet) // Set(1) { 'a' }

我们还可以使用数组来初始化一个 Set ,并且 Set 构造器会确保不重复地使用这些值。如:

    let mySet = new Set([1,2,1,1,2,3,4,5,5,5]);
    console.log(mySet.size); // 5
    console.log(mySet) // Set(5) { 1, 2, 3, 4, 5 }
    console.log(mySet.has(5)) // true
    console.log(mySet.has(6)) // false 因为6不在Set中所以打印为false

删除Set中的值

如果我们想要删除Set中的值可以直接使用delete() 方法来删除单个值,或者使用clear() 方法来清空Set。如:

    let mySet = new Set([1,2,1,1,2,3,4,5,5,5]);
    console.log(mySet.size); // 5
    console.log(mySet) // Set(5) { 1, 2, 3, 4, 5 }
    console.log(mySet.has(5)) // true

    mySet.delete(5); // 删除5
    console.log(mySet.size); // 4
    console.log(mySet) // Set(4) { 1, 2, 3, 4 }
    console.log(mySet.has(5)) // false 因为删除后找不到5了

Set 上的 forEach() 方法

Es6给Set添加了循环的方法forEach(),可以方便的处理其中的每一项数据。 forEach()方法会传入一个回调函数,回调函数可任意传入三个参数

Set 中下个位置的值; 与第一个参数相同的值; 目标 Set 自身。 传给回调函数的第一个与第二个 参数是相同的。(因为数组第二个参数参数的是索引值,但是Set没有键,所以就把自己的值当作键传入)除了参数差异外其他使用和数组基本相同。如:

    let mySet = new Set([1,2,1,1,2,3,4,5,5,5]);
    mySet.forEach((item, key, self) => {
        console.log(key + " " + item);
        console.log(self === mySet);
    });
    // 1 1
    // true
    // 2 2
    // true
    // 3 3
    // true
    // 4 4
    // true
    // 5 5
    // true

将 Set 转换为数组

上面说到创建Set可以传入一个数组进行创建,如果想要将Set转换为数组类型,使用…展开符即可。如:

    let mySet = new Set([1,2,1,1,2,3,4,5,5,5]);
    console.log([...mySet]); // [ 1, 2, 3, 4, 5 ]

上述代码,先是使用数组创建了Set,然后使用…展开符把Set重新转换为一个数组。而且还利用了Set类型的特性和转换方式一行代码就可以实现数组的去重。

实例操作方法
Set.prototype.constructor:构造函数,默认就是Set函数。
Set.prototype.size:返回Set实例的成员总数。
Set.prototype.add(value):添加某个值,返回 Set 结构本身。
Set.prototype.delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
Set.prototype.has(value):返回一个布尔值,表示该值是否为Set的成员。
Set.prototype.clear():清除所有成员,没有返回值。

Map和Set的区别

  • Map保存键值对,任何值都可以作为键值的值。
  • Set保存的是类数组数据,是值的集合。
  • Map有get方法而Set没有get方法
  • map以键值对的形式存储,key=value组成pair,是一组映射关系。set只有值,可以认为只有一个数据,并且set中元素不可以重复且自动排序。

数组转map:二维数组

var arr = [[ 1,"hello "],[2 , "hi" ],[3,{name: "jack"}]]

var m1=new Map(arr)

map转数组 :Array.form( ) 静态方法

var arr2=Array.from (m1)

console.log(arr1,m1,arr2,arr==arr2,arr[2] [1]==arr 2 [2] [1])

但是arr1!==arr2,m1当中传入的无论是集合还是数据都转化为数组,与原来并不一样。

引用数据内部并没有重新创建,所以arr[2] [1]==arr 2 [2] [1]为ture

var arr=[100,200,100,{age:20},{age:20}]

数组转集合

var s1=new Set (arr)

console.log(s1,s1.size)

集合转数组

var arr2 =array.from (s1)

console.log(arr,s1,arr2,arr[4]==arr2[3])

多个数组转集合和map

var arr1=[10,20]

var arr2=[100,200]

var arr3=[1000,2000]

var s1 = new Set ([...arr1,...arr2,...arr3])

var s1 = new Map ([arr1,arr2,arr3])