ES6+ 數(shù)據(jù)結構擴展
1. 前言
編程語言都具有內建的數(shù)據(jù)結構,但各種編程語言的數(shù)據(jù)結構常有不同之處。本文將要說的數(shù)據(jù)結構就是 JavaScript 內建的數(shù)據(jù)結構及其屬性。
我們知道在 JavaScript 中有兩種數(shù)據(jù)類型,一種是基本數(shù)據(jù)類型,另一種是引用類型。ES5 在數(shù)據(jù)存儲時一般使用 Array 或 Object 來存儲數(shù)據(jù)。然而,在越來越復雜的業(yè)務中數(shù)組和對象已經(jīng)不能滿足我們對數(shù)據(jù)的存儲要求了。ES6 新增了兩個用于儲存的數(shù)據(jù)結構 ——Set 和 Map,極大地豐富了 JS 數(shù)據(jù)存儲的能力。
2. Set 數(shù)據(jù)結構
ES5 中 JavaScript 中沒有所謂的集合概念,但是在其他一些語言如:C++、Java、python 等很早就有集合的概念了。ES6 對集合的數(shù)據(jù)結構進行了補充,引入了 Set 數(shù)據(jù)結構。
Set
對象允許你存儲任何類型的值,且存儲的值是唯一的,存儲的值可以是原始類型或者是引用類型。并且 Set 對象提供了讀、寫、查找和遍歷等方法,用以更加靈活地操作數(shù)據(jù)。
Set
是一個構造函數(shù),在使用時必須要使用 new 來創(chuàng)建一個實例,創(chuàng)建的實例基本上可以當作數(shù)組來使用。構造方法如下:
var set = new Set([iterable]);
在 new Set()
時,可以接收一個默認值作為參數(shù),這個參數(shù)需要滿足 可迭代 的要求。
下面我們看下方法的使用實例:
// 創(chuàng)建一個空的 Set 實例
var set = new Set() // Set(0) {}
// 添加數(shù)據(jù)
set.add('es6') // Set(1) {"es6"}
// 還可以鏈式添加數(shù)據(jù)
set.add('imooc').add('7') // Set(3) {"es6", "imooc", "7"}
// 接受一個可遍歷的對象,作為默認值,大部分情況是數(shù)組
var set = new Set([1, 2, 3])
console.log(set) // Set(3) {1, 2, 3}
上面的實例就是使用 Set
操作數(shù)據(jù)的過程,和數(shù)字不同的是對于數(shù)據(jù)的增刪改查 Set 都有對應的方法,而數(shù)字則通過索引的方式來實現(xiàn)的,這樣在一定情況下會出現(xiàn)不可控的因素。后面的章節(jié)我們會對 Set
做詳細的學習。
3. Map
我們都知道 Object 對象的鍵只能是基本類型,大部分情況都是字符串,并且 Object 存儲的數(shù)據(jù)是無序的,不能記住插入的先后順序。
ES6 為了彌補 Object 的缺陷,新增了 Map 數(shù)據(jù)結構用于存儲復雜的數(shù)據(jù)類型。Map 保存的是鍵值對,并且能夠記住鍵的插入順序,而且任何值都可以作為 Map 的鍵來使用,包括引用類型。
和 Set
一樣,Map
也是一個構造函數(shù),需要通過 new
的方式來創(chuàng)建一個 Map
實例。
var map = Map([iterable]);
在創(chuàng)建 Map
實例時可以接收一個特定的二維數(shù)組或是一個可遍歷的對象作為參數(shù),這個參數(shù)內的每一項是以鍵和值的方式來組合的,如: [key, value]
形式,第一個元素鍵,第二個元素是值。
// 創(chuàng)建一個空的 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}
// 接收一個二維數(shù)組,二維數(shù)組中包含兩個值,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
上面的代碼展示了 Map
數(shù)據(jù)結構添加和獲取操作,和 Set
一樣,Map
操作數(shù)據(jù)也是通過函數(shù)的方式來實現(xiàn)的。后面的章節(jié)我們會對 Map
做詳細的學習
4. 數(shù)據(jù)轉換
上面說到的 Set 和 Map 數(shù)據(jù)結構的簡單使用,它們還可以和數(shù)組和對象進行對應的轉換。這對于數(shù)據(jù)的操作是非常友好的。下面我們來看下 Set、Map 和 Array、Object 是如何進行轉化的。
4.1 Set 轉 Array
使用擴展運算符(...
)可以將 Set 數(shù)據(jù)結構轉化數(shù)組形式:
var set = new Set([1, 2, 3, 4]);
var a = [...set]
console.log(a) // [1,2,3,4]
還可以是 ES6 中數(shù)組提供的 Array.from()
進行轉化。
var set = new Set([1, 2, 3, 4]);
Array.from(set) //輸出[1,2,3,4]
4.2 Array 轉 Map
上文中學習了將一個帶鍵值對的二維數(shù)組傳入 Map 構造函數(shù),就可以得到一個 Map 數(shù)據(jù)結構,這樣就可以實現(xiàn)數(shù)組轉為 Map。
var map = new Map([['name', 'imooc'], [{name: 'imooc'}, ['JavaScript', 'ES6 wiki']]]);
上面代碼打印后的結果如下圖,引用類型也可以作為 Map 的鍵保存。
4.3 Map 轉 Array
上面我們看到了二維數(shù)組轉為 Map 數(shù)據(jù)結構,那么 Map 數(shù)據(jù)結構怎么轉回數(shù)組呢?其實很簡單,和前面已經(jīng)提過的 Set 轉數(shù)組的方式一樣,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"}
上面的代碼中,我們創(chuàng)建了一個方法用于 Object 轉 Map 使用,函數(shù)內部先構造一個 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. 小結
本節(jié)主要學習了 ES6 新增的數(shù)據(jù)結構 Set 和 Map 的基本使用,并介紹了 Set 和 Map 與 Array 和 Object 之間的轉化方法。從上面的學習中我們知道,ES6 新增 Set 和 Map 這兩個數(shù)據(jù)結構,在彌補 JavaScript 數(shù)據(jù)結構的同時并規(guī)范了操作數(shù)據(jù)的方法。讓 JavaScript 更加像一門成熟的語言前進。接下來的幾個小節(jié)我們會對 Set 和 Map 進行詳細的介紹。