ES6+ 数据结构扩展
1. 前言
编程语言都具有内建的数据结构,但各种编程语言的数据结构常有不同之处。本文将要说的数据结构就是 JavaScript 内建的数据结构及其属性。
我们知道在 JavaScript 中有两种数据类型,一种是基本数据类型,另一种是引用类型。ES5 在数据存储时一般使用 Array 或 Object 来存储数据。然而,在越来越复杂的业务中数组和对象已经不能满足我们对数据的存储要求了。ES6 新增了两个用于储存的数据结构 ——Set 和 Map,极大地丰富了 JS 数据存储的能力。
2. Set 数据结构
ES5 中 JavaScript 中没有所谓的集合概念,但是在其他一些语言如:C++、Java、python 等很早就有集合的概念了。ES6 对集合的数据结构进行了补充,引入了 Set 数据结构。
Set
对象允许你存储任何类型的值,且存储的值是唯一的,存储的值可以是原始类型或者是引用类型。并且 Set 对象提供了读、写、查找和遍历等方法,更加灵活地操作数据。
Set
是一个构造函数,在使用时必须去 new 一个实例,而 Set 实例基本都是当作数组来使用。构造方法如下:
var set = new Set([iterable]);
在构造 Set
时,它可以接收一个默认参数,这个参数需要满足可迭代的要求。
下面我们看下这些方法的使用实例:
// 创建一个空的 Set 实例
var set = new Set() // Set(0) {}
// 添加数据
set.add('es6') // Set(1) {"es6"}
// 还可以链式添加数据
set.add('imooc').add('7') // Set(3) {"es6", "imooc", "7"}
// 接受一个可遍历的对象,作为默认值,大部分情况是数组
var set = new Set([1, 2, 3])
console.log(set) // Set(3) {1, 2, 3}
上面的实例就是使用 Set
操作数据的过程,后面的章节我们会对 Set
做详细的学习。
3. Map
我们都知道 Object 对象的键值只能是基本类型,大部分情况都是字符串,并且 Object 存储的数据是无序的,不能记住插入的先后顺序。
ES6 为了弥补 Object 的缺陷,新增了 Map 数据结构用于存储复杂的数据类型。Map 保存的是键值对,并且能够记住键的插入顺序,而且任何值都可以作为 Map 的键来使用,包括对象类型。
和 Set
一样,Map
也是一个构造函数,需要通过 new
的方式来创建一个 Map
实例。
var map = Map([iterable]);
在创建 Map
实例时可以接收一个数组或是一个可遍历的对象作为参数,这个参数内的每一项是以键值组合的 [key, value]
形式,第一个元素键,第二个元素是值。
// 创建一个空的 Map 对象
var map1 = new Map()
map1.set('a', 1);
map1.set('b', 2);
map1.set('c', 3);
console.log(map1) // Map(3) {"a" => 1, "b" => 2, "c" => 3}
// map也可以进行链式调用
var map2 = new Map()
map2.set('a', 1).set('b', 2).set('c', 3)
console.log(map2) // Map(3) {"a" => 1, "b" => 2, "c" => 3}
// 接收一个二维数组,二维数组中包含两个值,key和value
var map3 = new Map([["x", 10], ["y", 20], ["z", 30]]);
console.log(map3) // Map(3) {"x" => 10, "y" => 20, "z" => 30}
console.log(map1.get('a')) // 1
console.log(map3.get('z')) // 30
4. 数据转换
上面说到的 Set 和 Map 数据结构,可以转换为数组或对象,这对于数据的操作是非常好的。下面我们来看下 Set、Map 和 Array、Object 是如何进行转化的。
4.1 Set 转 Array
使用扩展运算符(...
)可以将 Set 数据结构转化数组形式:
var set = new Set([1, 2, 3, 4]);
var a = [...set]
console.log(a) // [1,2,3,4]
还可以是 ES6 中数组提供的 Array.from()
进行转化。
var set = new Set([1, 2, 3, 4]);
Array.from(set) //输出[1,2,3,4]
4.2 Array 转 Map
上文中学习了将一个带键值对的二维数组传入 Map 构造函数,就可以转为 Map 结构,这样就可以实现数组转为 Map。
var map = new Map([['name', 'imooc'], [{name: 'imooc'}, ['JavaScript', 'ES6 wiki']]]);
上面代码打印后的结果如下图,引用类型也可以作为 Map 的键保存。
4.3 Map 转 Array
上文在学习 Map 时,我们知道在初始化时可以接收一个含键值对的二维数组,就可以得到一个 Map 数据结构。那么 Map 数据结构怎么转为数组呢?
其实很简单,和前面已经提过的 Set 转数组一样,Map 也可以使用扩展运算符 (…) 进行转换。
const map = new Map()
map.set('name', 'imooc')
map.set({name: 'imooc'}, ['JavaScript', 'ES6 wiki']);
[...myMap]
// [['name', 'imooc'], [{name: 'imooc'}, ['JavaScript', 'ES6 wiki']]]
4.4 Object 转 Map
Object 转 Map 没有一步到位的方法,需要去遍历 Object 然后逐个添加。
function objToMap(obj){
let map = new Map();
for (let [key, value] of Object.entries(obj)){
map.set(key, value);
}
return map;
}
objToMap({name:'imooc', lesson: 'ES6 Wiki'})
// Map(2) {"name" => "imooc", "lesson" => "ES6 Wiki"}
上面的代码中,我们创建了一个方法用于 Object 转 Map 使用,函数内部先构造一个 Map 实例,然后对 Object 进行遍历,逐个添加到 Map 实例上。
4.5 Map 转 Object
在 Map 转 Object 时需要注意的是,因为 Map 实例上的键可以是任意类型,而 Object 上的键只能是字符串类型。所有,如果 Map 的键都是字符串,它可以转为对象,如果键是一个对象,在转为对象时会被进行 toString
操作。
function mapToObj(map){
const obj = {}
for (let [key, value] of map){
obj[key] = value;
}
return obj;
}
const map1 = new Map()
map1.set('name', 'imooc')
map1.set('lesson', 'ES6 Wiki');
mapToObj(map1) // {name: "imooc", lesson: "ES6 Wiki"}
const map2 = new Map()
map2.set('name', 'imooc')
map2.set({name: 'lesson'}, ['JavaScript', 'ES6 wiki']);
mapToObj(map2) // {name: "lesson", [object Object]: ["JavaScript", "ES6 wiki"]}
上面的代码中需要注意的是 map2,它的第二个元素的键是一个对象,在转换对象的键时进行了 toString
操作,变成字符串 [object Object]
。
5. 小结
本节主要学习了 ES6 新增的数据结构 Set 和 Map 的基本使用,并介绍了 Set 和 Map 与 Array 和 Object 之间的转化方法。
让我们清晰地认识到为什么 ES6 新增 Set 和 Map 这两个数据结构,也让我们知道 Set、Map 和 Array、Object 之间的区别,在不同的数据存储场景选择不同的方式来存储数据。接下来的几个小节会对 Set 和 Map 进行详细的介绍。
- 还没有人评论,欢迎说说您的想法!