【讀書筆記】ES6 第11章 Set 和 Map 數據結構

第11章 Set 和 Map 數據結構

參考資料:《ES6標準入門第3版》

目錄

第11章 Set 和 Map 數據結構

11.1 Set 數據結構

11.1.1 基本用法

11.1.2 Set 實例的屬性和方法

11.1.3 遍歷操作

11.2 Map 結構

11.2.1 基本用法

11.2.2 Map 實例的屬性和方法

11.2.3 Map 遍歷方法

11.2.4 Map 與其他數據類型的轉換


11.1 Set 數據結構

11.1.1 基本用法

ES6 提供了新的數據結構 Set。它類似於數組,但是成員的值都是唯一的,沒有重複的值。相當於數學中的集合。

Set本身是一個構造函數,用來生成 Set 數據結構。

1. Set 結構不會添加重複的值。

const s = new Set();

[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));

for (let i of s) {
  console.log(i);
}
// 2 3 5 4

跟數組不一樣,Set 實例通過 add() 方法添加成員,在添加成員的時候,若Set 結構中已經存在該值,則該成員不會被添加。

2. Set 函數可以接受一個數組作爲參數來初始化

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

console.log([...set])
// [1, 2, 3, 4]

console.log(set.size)
// 4

訪問 Set 數據結構的變量的大小隻能通過 set.size 來訪問,set.length 結果是 undefined

3. Set 數據結構中的類型判斷

由於 Set 數據結構的特性,可以很方便地實現去除數組重複成員。

var array = [1, 2, 3, 3, 4, 4, 5, 5]
var newarray = [...new Set(array)]
console.log(newarray)
// [ 1, 2, 3, 4, 5 ]

這裏有必要討論下 Set 如何判斷兩個值是否相等。

Set 對加入的值不會發生類型轉換,5 和 “5” 是兩個不同的值。

const set = new Set()
set.add(5)
set.add('5')
console.log(set.size) // 2

Set 內部判斷兩個值的是否相同的方法類似於精確相等運算符( === ),不同的是在 Set 結構中 NaN 等於本身,而精確相等運算符認爲 NaN 不等於本身。

console.log(NaN === NaN)
// false 

const set = new Set()
set.add(NaN)
set.add(NaN)
console.log(set.size)
// size = 1, 說明在 set 內部認爲 NaN 相等,只添加了一個值

另外,無論對象是否爲空,兩個對象總是不相等。

const set = new Set()
set.add({})
set.add({})
console.log(set.size) // 2

11.1.2 Set 實例的屬性和方法

Set 結構的實例有以下屬性:

  • Set.prototype.constructor:構造函數,默認就是Set函數。
  • Set.prototype.size:返回Set實例的成員總數。

Set 結構有如下方法:

  • add(value):添加某個值,返回 Set 結構本身。
  • delete(value):刪除某個值,返回一個布爾值,表示刪除是否成功。
  • has(value):返回一個布爾值,表示該值是否爲Set的成員。
  • clear():清除所有成員,沒有返回值

11.1.3 遍歷操作

Set 結構的實例有四個遍歷方法,可以用於遍歷成員。

  • keys():返回鍵名的遍歷器
  • values():返回鍵值的遍歷器
  • entries():返回鍵值對的遍歷器
  • forEach():使用回調函數遍歷每個成員

由於 Set 結構沒有鍵名,只有鍵值(或者說鍵名和鍵值是同一個值),所以keys方法和values方法的行爲完全一致。

let set = new Set(['red', 'green', 'blue']);

for (let item of set.keys()) {
  console.log(item);
}
// red
// green
// blue

for (let item of set.values()) {
  console.log(item);
}
// red
// green
// blue

for (let item of set.entries()) {
  console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]

Set 結構的實例默認可遍歷,可以省略values方法,直接用for...of循環遍歷 Set。

let set = new Set(['red', 'green', 'blue']);

for (let x of set) {
  console.log(x);
}
// red
// green
// blue

11.2 Map 結構

11.2.1 基本用法

ES6 提供了 Map 數據結構,它類似於對象,也是鍵值對的集合,但是“鍵”的範圍不限於字符串,各種類型的值(包括對象)都可以當作鍵。

const map = new Map();

const object = { 
	word: 'Hello World'
};

map.set(object, 'content')

console.log(map.get(object)) // "content"

console.log(map.has(object)) // true

map.delete(object) // true

console.log(map.has(object)) // false

上面的例子就是把一個對象當做 map 的一個鍵,把一個字符串 “content” 作爲該對象鍵對應的值,map 可以正常讀取、或刪除這個鍵值對。

Map 結構除了可以使用 set 方法來添加成員,也可以接受一個數組作爲參數,該數組的成員是一個個表示鍵值對的數組。

const items = [
	  ['name1', '張三'],
	  ['name2', '李四']
];

const map = new Map(items);

console.log(map.size)  // 2

console.log(map.has('name1')) // true

console.log(map.get('name1')) // 張三

如果對同一個鍵多次賦值,後面的值將會覆蓋前面的值。

const map = new Map();

map
.set(1, 'aaa')
.set(1, 'bbb');

map.get(1) // "bbb"

讀取一個未知的值返回 undefined。

new Map().get('abc') 
// undefined

注意點:

1. 只有對同一個對象的引用,Map 結構纔將其視爲同一個鍵。

const map = new Map();

let b = ['b']

map.set(['a'], 555)
map.get(['a']) // undefined

map.set(b, 666)
map.get(b) // 666

2. 如果 Map 的鍵是一個簡單類型的值(數字、字符串、布爾值),則只要兩個值嚴格相等,Map 將其視爲一個鍵。

let map = new Map();

map.set(-0, 123);
map.get(+0) // 123

map.set(true, 1);
map.set('true', 2);
map.get(true) // 1

map.set(undefined, 3);
map.get(undefined) // 3

map.set(null, 4);
map.get(null) // 4


map.set(NaN, 123);
map.get(NaN) // 123

在上述代碼的描述中,+0 與 -0 相等,同時 Map 將 NaN 視爲同一個鍵,null 和 undefined 也被視爲不同的鍵。

11.2.2 Map 實例的屬性和方法

(1)size 屬性 :size 屬性返回 Map 結構的成員總數。

(2)set(key, value) :set方法設置鍵名key對應的鍵值爲value,然後返回整個 Map 結構。如果key已經有值,則鍵值會被更新,否則就新生成該鍵。

set方法返回的是當前的Map對象,因此可以採用鏈式寫法。

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

(3)get(key):get方法讀取key對應的鍵值,如果找不到key,返回undefined

(4)has(key):has方法返回一個布爾值,表示某個鍵是否在當前 Map 對象之中。

(5)delete(key):delete方法刪除某個鍵,返回true。如果刪除失敗,返回false

(6)clear():clear方法清除所有成員,沒有返回值。

11.2.3 Map 遍歷方法

Map 結構原生提供三個遍歷器生成函數和一個遍歷方法。

  • keys():返回鍵名的遍歷器。
  • values():返回鍵值的遍歷器。
  • entries():返回所有成員的遍歷器。
  • forEach():遍歷 Map 的所有成員。

需要特別注意的是,Map 的遍歷順序就是插入順序。

const map = new Map([
  ['F', 'no'],
  ['T',  'yes'],
]);

for (let key of map.keys()) {
  console.log(key);
}
// "F"
// "T"

for (let value of map.values()) {
  console.log(value);
}
// "no"
// "yes"

for (let item of map.entries()) {
  console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"

// 或者
for (let [key, value] of map.entries()) {
  console.log(key, value);
}
// "F" "no"
// "T" "yes"

// 等同於使用map.entries()
for (let [key, value] of map) {
  console.log(key, value);
}
// "F" "no"
// "T" "yes"

11.2.4 Map 與其他數據類型的轉換

1. Map 與數組的互相轉換

Map 結構轉換爲數組結構的比較快速的方法是結合擴展運算符 (...)。

const map = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);

console.log([...map])
// [ [ 1, 'one' ], [ 2, 'two' ], [ 3, 'three' ] ]

數據結構轉爲Map直接將數組作爲參數傳入Map構造函數就可以了,就如上述代碼中的數組所示。

2. Map 與對象的互相轉換

如果所有 Map 的鍵都是字符串,它可以無損地轉爲對象。

function strMapToObj(strMap) {
  let obj = Object.create(null);
  for (let [k,v] of strMap) {
    obj[k] = v;
  }
  return obj;
}

const myMap = new Map()
  .set('yes', true)
  .set('no', false);
strMapToObj(myMap)
// { yes: true, no: false }

如果有非字符串的鍵名,那麼這個鍵名會被轉成字符串,再作爲對象的鍵名。

對象轉爲 Map,本質上就是遍歷對象的所有屬性,然後用 set 方法爲 Map 結構添加成員。

function objToStrMap(obj) {
  let strMap = new Map();
  for (let k of Object.keys(obj)) {
    strMap.set(k, obj[k]);
  }
  return strMap;
}

objToStrMap({yes: true, no: false})
// Map {"yes" => true, "no" => false}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章