ECMAscript6——2

(5)Set数据结构

ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

Set本身是一个构造函数,用来生成Set数据结构。

var s = new Set();

[2,3,5,4,5,2,2].map(x => s.add(x))
for (i of s) {console.log(i)}
// 2 3 4 5

上面代码表示,set数据结构不会添加重复的值。

set数据结构有以下属性和方法:

size:返回成员总数。
add(value):添加某个值。
delete(value):删除某个值。
has(value):返回一个布尔值,表示该值是否为set的成员。
clear():清除所有成员。
s.add("1").add("2").add("2");
// 注意“2”被加入了两次

s.size // 2

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

s.delete("2");
s.has("2") // false
(6)Map数据结构
ES6还提供了map数据结构。它类似于对象,就是一个键值对的集合,但是“键”的范围不限于字符串,甚至对象也可以当作键。

var m = new Map();

o = {p: "Hello World"};
m.set(o, "content")
console.log(m.get(o))
// "content"
上面代码将一个对象当作m的一个键。

Map数据结构有以下属性和方法:

 

size:返回成员总数。
set(key, value):设置一个键值对。
get(key):读取一个键。
has(key):返回一个布尔值,表示某个键是否在Map数据结构中。
delete(key):删除某个键。
clear():清除所有成员。
var m = new Map();

m.set("edition", 6) // 键是字符串
m.set(262, "standard") // 键是数值
m.set(undefined, "nah") // 键是undefined

var 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
m.has(hello) // true

m.delete(undefined)
m.has(undefined) // false

m.get(hello) // Hello ES6!
m.get("edition") // 6
(7).rest(...)运算符

(1)基本用法

ES6引入rest运算符(...),用于获取函数的多余参数,这样就不需要使用arguments.length了。rest运算符后面是一个数组变量,该变量将多余的参数放入数组中。

function add(...values) {
let sum = 0;

for (var val of values) {
sum += val;
}

return sum;
}

add(2, 5, 3) // 10
上面代码的add函数是一个求和函数,利用rest运算符,可以向该函数传入任意数目的参数。

下面是一个利用rest运算符改写数组push方法的例子。

function push(array, ...items) {
items.forEach(function(item) {
array.push(item);
console.log(item);
});
}

var a = [];
push(a, "a1", "a2", "a3", "a4");

(2)将数组转为参数序列

rest运算符不仅可以用于函数定义,还可以用于函数调用。

 

function f(s1, s2, s3, s4, s5) {
console.log(s1 + s2 + s3 + s4 +s5);
}

 

var a = ["a2", "a3", "a4", "a5"];

 

f("a1", ...a)
// a1a2a3a4a5

从上面的例子可以看出,rest运算符的另一个重要作用是,可以将数组转变成正常的参数序列。利用这一点,可以简化求出一个数组最大元素的写法。

// ES5
Math.max.apply(null, [14, 3, 77])

// ES6
Math.max(...[14, 3, 77])

// 等同于
Math.max(14, 3, 77);

上面代码表示,由于JavaScript不提供求数组最大元素的函数,所以只能套用Math.max函数,将数组转为一个参数序列,然后求最大值。有了rest运算符以后,就可以直接用Math.max了。

 

(8)遍历器(Iterator)

遍历器(Iterator)是一种协议,任何对象都可以部署遍历器协议,从而使得for...of循环可以遍历这个对象。

遍历器协议规定,任意对象只要部署了next方法,就可以作为遍历器,但是next方法必须返回一个包含value和done两个属性的对象。其中,value属性当前遍历位置的值,done属性是一个布尔值,表示遍历是否结束。

 

下面是一个无限运行的遍历器的例子。

 

function idMaker(){
var index = 0;

return {
next: function(){
return {value: index++, done: false};
}
}
}

 

var it = idMaker();

 

it.next().value // '0'
it.next().value // '1'
it.next().value // '2'
// ...

(9)generator函数

ECMAscript6引入了genertor函数,作用就是返回一个内部状态的遍历器,主要特征是函数内部使用了yield语句。

 

当调用generator函数的时候,该函数并不执行,而是返回一个遍历器(可以理解成暂停执行)。以后,每次调用这个遍历器的next方法,就从函数体的头部或者上一次停下来的地方开始执行(可以理解成恢复执行),直到遇到下一个yield语句为止,并返回该yield语句的值。

 

ECMAScript 6草案定义的generator函数,需要在function关键字后面,加一个星号。然后,函数内部使用yield语句,定义遍历器的每个成员。

yield有点类似于return语句,都能返回一个值。区别在于每次遇到yield,函数返回紧跟在yield后面的那个表达式的值,然后暂停执行,下一次从该位置继续向后执行,而return语句不具备位置记忆的功能。

hw.next()
// { value: 'hello', done: false }

hw.next()
// { value: 'world', done: false }

hw.next()
// { value: undefined, done: true }

hw.next()
// Error: Generator has already finished
// at GeneratorFunctionPrototype.next (native)
// at repl:1:3
// at REPLServer.defaultEval (repl.js:129:27)
// ...
上面代码一共调用了四次next方法。

第一次调用:函数开始执行,直到遇到第一句yield语句为止。next方法返回一个对象,它的value属性就是当前yield语句的值hello,done属性的值false,表示遍历还没有结束。

第二次调用:函数从上次yield语句停下的地方,一直执行到下一个yield语句。next方法返回一个对象,它的value属性就是当前yield语句的值world,done属性的值false,表示遍历还没有结束。

第三次调用:函数从上次yield语句停下的地方,一直执行到函数结束。next方法返回一个对象,它的value属性就是函数最后的返回值,由于上例的函数没有return语句(即没有返回值),所以value属性的值为undefined,done属性的值true,表示遍历已经结束。

第四次调用:由于此时函数已经运行完毕,next方法直接抛出一个错误。

遍历器的本质,其实是使用yield语句暂停执行它后面的操作,当调用next方法时,再继续往下执行,直到遇到下一个yield语句,并返回该语句的值,如果直到运行结束。

 

function* f() {
for(var i=0; true; i++) {
var reset = yield i;
if(reset) { i = -1; }
}
}

 

var g = f();

 

g.next() // { value: 0, done: false }
g.next() // { value: 1, done: false }
g.next(true) // { value: 0, done: false }

上面代码先定义了一个可以无限运行的generator函数f,如果next方法没有参数,正常情况下返回一个递增的i;如果next方法有参数,则上一次yield语句的返回值将会等于该参数。如果该参数为true,则会重置i的值。

 

 

 

 

 

 

 

posted @ 2015-12-29 22:12  小汤圆。  阅读(128)  评论(0编辑  收藏  举报