一、set

1.基本用法

  数据结构Set类似于数组,但是成员的值都是唯一的,没有重复的值。
    let s = new Set();
[2,3,5,4,5,2,2].map(x => s.add(x))
for (let i of s) {console.log(i)}// 2 3 5 4
//Set函数可以接受一个数组作为参数,用来初始化。 var items = new Set([1,2,3,4,5,5,5,5]);
console.log(items); // set object
console.log(items.size); //
//向Set加入值的时候,不会发生类型转换,所以5和“5”是两个不同的值。
let set = new Set();
set.add({})
console.log(set.size);//
set.add({})
console.log(set.size);//
//上面代码表示,由于两个空对象不是精确相等,所以它们被视为两个值。

2.Set实例的属性

Set结构的实例有以下属性。
Set.prototype.constructor:构造函数,默认就是Set函数。
Set.prototype.size:返回Set实例的成员总数。
    let s = new Set();
s.add(1).add(2).add(2);// 注意2被加入了两次
console.log(s);
console.log(s.size); //

3.Set实例的方法

分为两大类:
  操作方法(用于操作数据)和遍历方法(用于遍历成员)。下面先介绍四个操作方法。
  add(value):添加某个值,返回Set结构本身。
  delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
  has(value):返回一个布尔值,表示该值是否为Set的成员。
  clear():清除所有成员,没有返回值。
上面这些属性和方法的实例如下:
    let s = new Set();
s.add(1).add(2).add(2);
console.log(s.has(1));// true
console.log(s.has(2)); // true
console.log(s.has(3));// false
s.delete(2);
console.log(s.has(2));// false
s.clear();
console.log(s.size);//
//Array.from方法可以将Set结构转为数组:
let items = new Set([1, 2, 3, 4, 5]);
let array = Array.from(items);
console.log(array);//[1, 2, 3, 4, 5]

4.遍历操作

Set结构的实例有四个遍历方法,可以用于遍历成员。
  keys():返回一个键名的遍历器
  values():返回一个键值的遍历器
  entries():返回一个键值对的遍历器
  forEach():使用回调函数遍历每个成员
由于Set结构没有键名,只有键值(或者说键名和键值是同一个值),所以key方法和value方法的行为完全一致。
    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.forEach(function(item){
console.log(item);// red green blue
})

二、WeakSet

WeakSet和Set一样都不存储重复的元素,但有一些不同点 。
WeakSet的成员只能是对象,而不能是其他类型的值。
WeakSet结构有以下三个方法。
WeakSet.prototype.add(value):向WeakSet实例添加一个新成员。
WeakSet.prototype.delete(value):清除WeakSet实例的指定成员。
WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在
    let ws = new WeakSet();
//console.log(ws.add(1));// TypeError: Invalid value used in weak set
let obj = {};
let foo = {};
ws.add(window);
ws.add(obj);
console.log(ws);
console.log(ws.has(window)); // true
console.log(ws.has(foo)); // false
ws.delete(window);
console.log(ws.has(window)); // false
//WeakSet没有size属性,没有办法遍历它的成员。
console.log(ws.size) // undefined
console.log(ws.forEach); // undefined
//ws.forEach(function(item){ console.log('WeakSet has ' + item)})// TypeError: undefined is not a function

三、Map结构的目的和基本用法

Map 是一个“超对象”,其 key 除了可以是 String 类型之外,还可以为其他类型(如:对象)
他的方法和 Set 差不多:
  size:返回成员总数。
  set(key, value):设置一个键值对。
  get(key):读取一个键。
  has(key):返回一个布尔值,表示某个键是否在Map数据结构中。
  delete(key):删除某个键。
  clear():清除所有成员。
        let m = new Map();
o = {p: "Hello World"};
m.set(o, "content")
console.log(m);
console.log(m.get(o))// "content"

实例的属性和操作方法

Map结构的实例有以下属性和操作方法。
  size:返回成员总数。
  set(key, value):设置key所对应的键值,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就新生成该键。
  get(key):读取key对应的键值,如果找不到key,返回undefined。
  has(key):返回一个布尔值,表示某个键是否在Map数据结构中。
  delete(key):删除某个键,返回true。如果删除失败,返回false。
  clear():清除所有成员,没有返回值。
  set()方法返回的是Map本身,因此可以采用链式写法。
    let map = new Map()
.set(1, 'a')
.set(2, 'b')
.set(3, 'c');
console.log(map);
//下面是has()和delete()的例子。
let m = new Map();
m.set("edition", 6) // 键是字符串
m.set(262, "standard") // 键是数值
m.set(undefined, "nah") // 键是undefined
let hello = function() {console.log("hello");}
m.set(hello, "Hello ES6!") // 键是函数
m.has("edition") // true
m.has("years") // false
m.has(262) // true
m.has(undefined) // true
console.log(m.get(undefined));
m.has(hello) // true
m.delete(undefined)
m.has(undefined) // false
m.get(hello) // Hello ES6!
m.get("edition") //
//下面是size属性和clear方法的例子。
map.set('foo', true);
map.set('bar', false);
map.size //
map.clear()
map.size //
console.log(Array.from(m));//Array

遍历方法

  Map原生提供三个遍历器。
  keys():返回键名的遍历器。
  values():返回键值的遍历器。
  entries():返回所有成员的遍历器。
使用示例:
    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结构转为数组结构,比较快速的方法是结合使用扩展运算符(...)。

        let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three']
]);
[...map.keys()];
// [1, 2, 3]
[...map.values()];
// ['one', 'two', 'three']
[...map.entries()];
// [[1,'one'], [2, 'two'], [3, 'three']]
[...map]
// [[1,'one'], [2, 'two'], [3, 'three']]
//此外,Map还有一个forEach方法,与数组的forEach方法类似,也可以实现遍历。
map.forEach(function(value, key){
console.log(key+':'+value);
});

四、WeakMap

WeakMap结构与Map结构基本类似,唯一的区别是它只接受对象作为键名(null除外),不接受原始类型的值作为键名,而且键名所指向的对象,不计入垃圾回收机制。set()和get()分别用来添加数据和获取数据:
    let map = new WeakMap();
let element={};
map.set(element, "Original");
// 下面就可以使用了
let value = map.get(element);
console.log(value); // "Original"

WeakMap与Map在API上的区别主要是两个:

  一是没有遍历操作(即没有key()、values()和entries()方法),也没有size属性;
  二是无法清空,即不支持clear方法。这与WeakMap的键不被计入引用、被垃圾回收机制忽略有关。
因此,WeakMap只有四个方法可用:get()、set()、has()、delete()。

五、Iterator(遍历器)的概念

遍历器(Iterator)就是统一的接口机制,来处理所有不同的数据结构。

Iterator的作用有三个:

  一是为各种数据结构,提供一个统一的、简便的访问接口;
  二是使得数据结构的成员能够按某种次序排列;
  三是ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。

Iterator的遍历过程是这样的。

  创建一个指针,指向当前数据结构的起始位置。也就是说,遍历器的返回值是一个指针对象。
  第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
  第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
  调用指针对象的next方法,直到它指向数据结构的结束位置。
  每一次调用next方法,都会返回当前成员的信息,具体来说,就是返回一个包含value和done两个属性的对象。其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。
    function idMaker(){
var index = 0;
return {
next: function(){
return {value: index++, done: false};
}
}
}
let it = idMaker();
console.log(it.next().value); // '0'
console.log(it.next().value); // '1'
console.log(it.next().value); // '2'

数据结构的默认Iterator接口

在ES6中,可迭代数据结构(比如数组)都必须实现一个名为Symbol.iterator的方法,该方法返回一个该结构元素的迭代器。注意,Symbol.iterator是一个Symbol,Symbol是ES6新加入的原始值类型。
    let arr = ['a', 'b', 'c'];
let iter = arr[Symbol.iterator]();
console.log(iter);
console.log(iter.next()); // { value: 'a', done: false }
console.log(iter.next()); // { value: 'b', done: false }
console.log(iter.next()); // { value: 'c', done: false }
console.log(iter.next()); // { value: undefined, done: true }
上面代码中,变量arr是一个数组,原生就具有遍历器接口,部署在arr的Symbol.iterator属性上面。所以,调用这个属性,就得到遍历器。
调用默认Iterator接口的场合
有一些场合会默认调用iterator接口(即Symbol.iterator方法),除了下文会介绍的for...of循环,还有几个别的场合。

解构赋值

对数组和Set结构进行解构赋值时,会默认调用iterator接口。
    let set = new Set().add('a').add('b').add('c');
let [x,y] = set;
// x='a'; y='b'
let [first, ...rest] = set;
console.log(first);//'a'
console.log(rest);// ['b','c'];
//扩展运算符
//扩展运算符(...)也会调用默认的iterator接口。
// 例一
let str = 'hello';
console.log([...str]); // ['h','e','l','l','o']
// 例二
let arr = ['b', 'c'];
console.log(['a', ...arr, 'd']);// ['a', 'b', 'c', 'd']

其他场合

以下场合也会用到默认的iterator接口,可以查阅相关章节。
yield*
Array.from()
Map(), Set(), WeakMap(), WeakSet()
Promise.all(), Promise.race() 原生具备Iterator接口的数据结构
字符串是一个类似数组的对象,也原生具有Iterator接口。
    let someString = "hi";
typeof someString[Symbol.iterator]// "function"
let iterator = someString[Symbol.iterator]();
iterator.next() // { value: "h", done: false }
iterator.next() // { value: "i", done: false }
iterator.next() // { value: undefined, done: true }
//上面代码中,调用Symbol.iterator方法返回一个遍历器,在这个遍历器上可以调用next方法,实现对于字符串的遍历。
//可以覆盖原生的Symbol.iterator方法,达到修改遍历器行为的目的。
let str = new String("hi");
[...str] // ["h", "i"]
str[Symbol.iterator] = function() {
return {
next: function() {
if (this._first) {
this._first = false;
return { value: "bye", done: false };
} else {
return { done: true };
}
},
_first: true
};
};
[...str] // ["bye"]
str // "hi"
//上面代码中,字符串str的Symbol.iterator方法被修改了,所以扩展运算符(...)返回的值变成了bye,而字符串本身还是hi。

六、Iterator接口与Generator函数

Symbol.iterator方法的最简单实现,还是使用下一章要介绍的Generator函数。
    let myIterable = {};
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
console.log(myIterable);
console.log([...myIterable]); // [1, 2, 3] // 或者采用下面的简洁写法
let obj = {
* [Symbol.iterator]() {
yield 'hello';
yield 'world';
}
}; for (let x of obj) {
console.log(x);// hello world
}
//上面代码中,Symbol.iterator方法几乎不用部署任何代码,只要用yield命令给出每一步的返回值即可。

遍历器的return(),throw()

遍历器返回的指针对象除了具有next方法,还可以具有return方法和throw方法。其中,next方法是必须部署的,return方法和throw方法是否部署是可选的。
return方法的使用场合是,如果for...of循环提前退出(通常是因为出错,或者有break语句或continue语句),就会调用return方法。
如果一个对象在完成遍历前,需要清理或释放资源,就可以部署return方法。
throw方法主要是配合Generator函数使用,一般的遍历器用不到这个方法。

七、for...of循环

  迭代器对象允许像 CLI IEnumerable 或者 Java Iterable 一样自定义迭代器。
  将for..in转换为自定义的基于迭代器的形如for..of的迭代,不需要实现一个数组,支持像 LINQ 一样的惰性设计模式。
    let fibonacci = {
[Symbol.iterator]() {
let pre = 0, cur = 1;
return {
next() {
[pre, cur] = [cur, pre + cur];
return { done: false, value: cur }
}
}
}
}
console.log(fibonacci);
for (let n of fibonacci) {
// truncate the sequence at 1000
if (n > 1000){
break;
}
console.log(n);
}

 此篇终,待续……


es6笔记5^_^set、map、iterator的更多相关文章

  1. es6笔记(5)Map数据结构

    概要 字典是用来存储不重复key的Hash结构.不同于集合(Set)的一点,字典使用的是[key,value]的形式来存储数据. JavaScript的对象(Object:{})只能用字符串当做key ...

  2. ES6笔记(6)-- Set、Map结构和Iterator迭代器

    系列文章 -- ES6笔记系列 搞ES6的人也是够无聊,把JS弄得越来越像Java.C++,连Iterator迭代器.Set集合.Map结构都出来了,不知道说什么好... 一.简单使用 1. iter ...

  3. ES6学习笔记(10)----Set和Map数据结构

    参考书<ECMAScript 6入门>http://es6.ruanyifeng.com/ Set和Map数据结构 1.Set  基本用法    Set是一种新的数据结构,它的成员都是唯一 ...

  4. ES6 学习笔记(十)Map的基本用法

    1 基本用法 Map类型是键值对的有序列表,而键和值都可以是任意类型.可以看做Python中的字典(Dictionary)类型. 1.1 创建方法 Map本身是一个构造函数,用来生成Map实例,如: ...

  5. ES6笔记系列

    ES6,即ECMAScript 6.0,ES6的第一个版本是在2015年发布的,所以又称作ECMAScript 2015 如今距ES6发布已经一年多的时间,这时候才去学,作为一个JSer,羞愧羞愧,还 ...

  6. ES6笔记(3)-- 解构赋值

    系列文章 -- ES6笔记系列 解构赋值,即对某种结构进行解析,然后将解析出来的值赋值给相关的变量,常见的有数组.对象.字符串的解构赋值等 一.数组的解构赋值 function ids() { ret ...

  7. ES6笔记(5)-- Generator生成器函数

    系列文章 -- ES6笔记系列 接触过Ajax请求的会遇到过异步调用的问题,为了保证调用顺序的正确性,一般我们会在回调函数中调用,也有用到一些新的解决方案如Promise相关的技术. 在异步编程中,还 ...

  8. STL笔记(1)map

    STL笔记(1)map STL之map ZZ from http://hi.baidu.com/liyanyang/blog/item/d5c87e1eb3ba06f41bd576cf.html 1. ...

  9. ES6中的Set和Map集合

    前面的话 在ES6标准制定以前,由于可选的集合类型有限,数组使用的又是数值型索引,因而经常被用于创建队列和栈.如果需要使用非数值型索引,就会用非数组对象创建所需的数据结构,而这就是Set集合与Map集 ...

  10. ES6中的Set与Map数据结构

    本文实例讲述了ES6学习笔记之Set和Map数据结构.分享给大家供大家参考,具体如下: 一.Set ES6提供了新的数据结构Set.类似于数组,只不过其成员值都是唯一的,没有重复的值. Set本身是一 ...

随机推荐

  1. android usb挂载分析

    http://blog.csdn.net/new_abc/article/details/7409018

  2. DOM对象和JQuery对象进行转换

    var btn=document.getElementById("btn"); $(btn).click(function(){}); DOM对象转换为JQuery对象: 用$符号 ...

  3. java类到底是如何加载并初始化的?

    Java虚拟机如何把编译好的.class文件加载到虚拟机里面?加载之后如何初始化类?静态类变量和实例类变量的初始化过程是否相同,分别是如何初始化的呢?这篇文章就 是解决上面3个问题的. 若有不正之处, ...

  4. Ubuntu Server 14.04 & Apache2.4 虚拟主机、模块重写、隐藏入口文件配置

    环境: Ubuntu Server 14.04 , Apache2.4 一.Apache2.4 虚拟主机配置 01. 新建一份配置文件 在apache2.4中,虚拟主机的目录是通过/etc/apach ...

  5. [转]hibernate缓存机制所有详解

    以下文章来自http://www.blogjava.net/tbwshc/articles/380013.html Hibernate 所有缓存机制详解 hibernate提供的一级缓存 hibern ...

  6. ajax跨域实现api 接口调用

    背景: 想实现跨域去调用接口, 然后同时支持下次调用,能够带cookie信息过来,同时支持来自多个源头的域名的跨域调用. 1.这样支持来自所有域名的跨域调用: 不支持跨域是,浏览器报错: 在api接口 ...

  7. jquery刷新iframe页面的方法(兼容主流)

    1,reload 方法,该方法强迫浏览器刷新当前页面.语法:location.reload([bForceGet])   参数: bForceGet, 可选参数, 默认为 false,从客户端缓存里取 ...

  8. (简单) POJ 1860 Currency Exchange,SPFA判圈。

    Description Several currency exchange points are working in our city. Let us suppose that each point ...

  9. Undefined symbols for architecture i386: "_crc32", referenced from:——crc链接错误

    有时候用别人的框架,你会碰到下面的错误,很是吓人,什么玩意,我怎么看不懂!!! Undefined symbols for architecture i386:  "_RELEASE&quo ...

  10. Struts2动态方法调用

    动态方法就是一个Action对应多个请求,减少Action的数量 1.指定method属性 <action name="addAction" method="add ...