天天看點

ES6筆記(6)-- Set、Map結構和Iterator疊代器

系列文章 -- ES6筆記系列

搞ES6的人也是夠無聊,把JS弄得越來越像Java、C++,連Iterator疊代器、Set集合、Map結構都出來了,不知道說什麼好...

一、簡單使用

1. iterator

學過C++的人應該知道這是個疊代器對象,擁有一個指針,指向資料結構中的某個成員

JS中的iterator也有類似的功能,JS内部為一些資料結構實作了iterator疊代器的接口,讓我們可以友善的使用

var [a, b, ...c] = [1, 2, 3, 4];

c // [3, 4]      

如上,解構指派以及擴充運算符的便利,多虧了内部實作的預設iterator疊代器接口,可以使用其Symbol.iterator屬性獲得,如

var arr = [1, 2, 3];

var it = arr[Symbol.iterator]();

it.next() // {done: false, value: 1}
it.next() // {done: false, value: 2}
it.next() // {done: false, value: 3}
it.next() // {done: true, value: undefined}      

上述的iterator接口表現形式過于隐秘,在generator生成器函數中,我們可以看看比較顯示的iterator接口調用:

function* showNumbers() {
    yield 1;
    yield 2;
    yield 3;
}

var show = showNumbers();

show.next(); // {done: false, value: 1}
show.next(); // {done: false, value: 2
show.next(); // {done: true, value: 3}      

通過調用next方法,實作iterator疊代器的周遊

可見結果輸出是一個對象,該對象擁有done這個疊代器是否周遊完成的狀态,以及目前指向項的值

看到這裡,結合上述兩個例子,應該知道可以通過Symbol.iterator與generator的結合,建立出一個iterator疊代器,比如:

var obj = {};

obj[Symbol.iterator] = function* () {
  yield 1;
  yield 2;
  yield 3;
};

[...obj] // [1, 2, 3]      

既然隻有done與value兩個屬性,實作起來應該不是太難,我們可以嘗試實作一個基本的iterator

function myIterator(arr) {
    var nextIndex = 0;

    return {
        next: function() {
            return  nextIndex < arr.length
                ? {
                    value: arr[nextIndex++],
                    done: false
                }
                : {
                    value: undefined,
                    done: true
                }
        }
    }
}

var it = myIterator(['one', 'two']);

it.next() // {done: false, value: "one"}
it.next() // {done: true, value: "two"}
it.next() // {done: true, value: undefined}      

2. Set

Set是ES6中新引入的資料結構,它類似于數組,但是成員的值都是唯一的,沒有重複的值。

可以通過執行個體化其構造函數,用來生成Set資料結構,通過.add()方法插入值,通過for...of循環周遊相應值

var s = new Set();

var arr = [1, 2, 2, 3];

arr.forEach(function(item) {
    s.add(item);
});

for (var item of s) {
    console.log(item) // 1 2 3
}      

可見Set自動去除了重複的值,隻插入了一個2,由此在去除數組重複值的時候,可以更友善:

var arr = [1, 2, 2, 3];


function unique(arr) {
    return [...new Set(arr)];
}

unique(arr) // [1, 2, 3]      

不過,要注意的是,Set判斷是否重複,是使用到了全等===條件,即類型及值完全相等才擯除,不過NaN是例外

var arr = [1, 0, '', 3, false, 3, NaN, NaN];


function unique(arr) {
    return [...new Set(arr)];
}

unique(arr) // [1, 0, '', 3, false, NaN]      

set有一些屬性和方法:

  • Set.prototype.constructor

    :構造函數,預設就是

    Set

    函數。
  • Set.prototype.size

    :傳回

    Set

    執行個體的成員總數。
  • add(value)

    :添加某個值,傳回Set結構本身。
  • delete(value)

    :删除某個值,傳回一個布爾值,表示删除是否成功。
  • has(value)

    :傳回一個布爾值,表示該值是否為

    Set

    的成員。
  • clear()

    :清除所有成員,沒有傳回值。
var s = new Set();

s.add(1).add(2).add(2);

s.size // 2

s.has(1) // true
s.has(2) // true
s.has(3) // false

s.delete(2);
s.has(2) // false

s.clear()
s.has(1) // false      

set的一些周遊操作:

  • keys()

    :傳回鍵名的周遊器
  • values()

    :傳回鍵值的周遊器
  • entries()

    :傳回鍵值對的周遊器
  • forEach()

    :使用回調函數周遊每個成員

keys()、values()、entries()的使用

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"]      

forEach的使用

let set = new Set([1, 2, 3]);
set.forEach((value, key) => console.log(value * 2) )
// 2
// 4
// 6      

set與數組的轉換

數組轉換成set結構隻需要将數組加入到set構造函數參數中執行個體化即可

set集合轉換成數組,可簡單的使用擴充運算符...,也可使用Array.from()的新方法

var items = new Set([1, 2, 3, 4, 5]);
var array1 = Array.from(items);

var array2 = [...items]

array1 // [1, 2, 3, 4, 5]
array2 // [1, 2, 3, 4, 5]      

3. Map

Map也是ES6中新引入的資料結構,它類似于Hash結構,屬于鍵=>值對的結構,每一項值可用key=>value來表示

通過執行個體化構造函數生成一個map對象,再通過.set方法設定相關項的鍵值對,通過.get方法擷取相應的鍵值對

var m = new Map();
var obj = {str: 'str'};

m.set(obj, 'content');
m.get(obj) // "content"      

也可以直接在構造函數中加入一個數組參數,直接執行個體化出map對象

var map = new Map([
  ['name', '張三'],
  ['title', 'Author']
]);

map.size // 2
map.has('name') // true
map.get('name') // '張三''
map.has('title') // true
map.get('title') // 'Author'      

類似Set,Map也有一些常見的屬性和方法

  • size屬性 傳回Map結構的成員總數。
  • set(key, value) 設定

    key

    所對應的鍵值,然後傳回整個Map結構。如果

    key

    已經有值,則鍵值會被更新,否則就新生成該鍵
  • get(key) 讀取

    key

    對應的鍵值,如果找不到

    key

    ,傳回

    undefined

  • has(key) 傳回一個布爾值,表示某個鍵是否在Map資料結構中
  • delete(key) 删除某個鍵,傳回true。如果删除失敗,傳回false
  • clear() 清除所有成員,沒有傳回值。

類似Set,Map也有一些常見的周遊方法

  • keys()

    :傳回鍵名的周遊器。
  • values()

    :傳回鍵值的周遊器。
  • entries()

    :傳回所有成員的周遊器。
  • forEach()

    :周遊Map的所有成員
let 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);
}

// 等同于使用map.entries()
for (let [key, value] of map) {
  console.log(key, value);
}      

Map與數組的轉換

與Set一樣,Map和數組直接也可以互相轉換

使用擴充運算符...可以将Map轉換為數組

let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
[...myMap]
// [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]      

執行個體化Map構造函數時傳入參數可将數組轉換為Map對象

new Map([[true, 7], [{foo: 3}, ['abc']]])
// Map {true => 7, Object {foo: 3} => ['abc']}      

4. WeakSet

...

5. WeakMap

後記:

ES6的内容實在是太多了,打算閱讀相關新特性文檔後做個筆記,蓦然發現經常會不耐煩

文章不知從何寫起,不知如何布局文章内容結構,寫完之後又覺得不夠全面或者了解還未到位,每每想不再繼續

寫到這篇set和map,已經沒啥耐心寫下去了

還是好好看看其他人的總結吧,全面許多

[-_-]眼睛累了吧,注意勞逸結合呀[-_-]

繼續閱讀