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,已经没啥耐心写下去了 还是好好看看其他人的总结吧,全面许多 完

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏柠檬先生

你不知道的javaScript笔记(4)

类型: JavaScript 有7种内置类型 空值 (null) 未定义(undefined) 布尔值(boolean) 数字(number) 字符串(stri...

22850
来自专栏彭湖湾的编程世界

【java】java反射初探 ——“当类也学会照镜子”

反射的作用 开门见山地说说反射的作用 1.为我们提供了全面的分析类信息的能力 2.动态加载类 我理解的“反射”的意义 (仅个人理解哈) 我理解的java反射机制...

273100
来自专栏微信公众号:Java团长

Java反射机制深入详解

  反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个java的类获取他所有的成员变量和...

7110
来自专栏take time, save time

初级程序员面试不靠谱指南(三)

二、指针的好基友的& 1.&的意义。说&是指针的好基友其实不恰当,因为&这个符号在C/C++不止有一种含义,但是因为其经常会和指针一起出现在被问的问题列表上,所...

33890
来自专栏Android干货园

Kotlin中级(9)- - - Kotlin类之数据类、密封类、内部类.md

上面的代码我们可以看到结构出来的变脸可以直接拿来用,比如数据体Leaf中的size属性,componentN函数群会按照数据体Leaf中属性声明的顺序,从com...

10820
来自专栏云霄雨霁

Java--多态性之嵌套类

15650
来自专栏我和PYTHON有个约会

32.企业级开发进阶4:正则表达式

本节内容,要讲解的和我们的信息检索有关系,这一方面也是Python在目前非常流行的一个应用方向:爬虫。

10610
来自专栏java一日一条

Java的常见误区与细节

1 在Java中,没有goto语句。因为大量使用goto语句会降低程序的可读性和可维护性,所以Java语言取消了goto的使用。同时,为了避免程序员自行使用...

13130
来自专栏吾爱乐享

java之学习Integer的自动装箱和自动拆箱(JDK5新特性)

12130
来自专栏一个会写诗的程序员的博客

第3章 Kotlin 可空类型与类型系统第3章 Kotlin 可空类型与类型系统

我们在编程语言中使用类型的目的是为了让编译器能够确定类型所关联的对象需要分配多少空间。

14220

扫码关注云+社区

领取腾讯云代金券