Lesson-8 ES6 高级语法(1)
新增关键字 let const
首先必须要记住的是这里的let和swift中的let完 全不同,并不是表示常量,而是var的变种
- 不允许重复声明
- 不会提升 也就是说在声明这个变量之前是不能使用的
*在ES6中添加块级作用域,简单理解就是所有的{}中间,let const都可以响应这些作用域,而var是不能响应的 他只能响应全局和函数作用域
const 表示常量 不能修改 其他和let一样 而且如果需要为模块添加对外暴露的常量 如下定义export const A = 1;
允许结构赋值
- 可以缺省
- 可以设置默认值
var [a, b, c] = [1, 2, 3];
let [,,third] = ["foo", "bar", "baz"];
let [a, [b], d] = [1, [2, 3], 4];
[x, y='b'] = ['a'] // x='a', y='b'
[x, y='b'] = ['a', undefined] // x='a', y='b'
let [v1, v2, ..., vN ] = array;
[a, b, c] = new Set(["a", "b", "c"])
function* fibs() {
var a = 0;
var b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
var [first, second, third, fourth, fifth, sixth] = fibs();
sixth // 5
上面代码中,fibs是一个Generator函数,原生具有Iterator接口。解构赋值会依次从这个接口获取值。
解构赋值还可以用在对象的赋值上
//直接赋值
var { foo, bar } = { foo: "aaa", bar: "bbb" };
//属性名不一样的时候
var { foo: baz } = { foo: "aaa", bar: "bbb" };
//
这个东西可以直接交换 也可以返回多个值 有点类似swift中的元组
Iterator(遍历器)
简单来说就是获取这个类的某个指针,然后可以调用他的next方法进行遍历
Iterator的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。
let arr = ['a', 'b', 'c'];
let iter = arr[Symbol.iterator]();
iter.next() // { value: 'a', done: false }
iter.next() // { value: 'b', done: false }
iter.next() // { value: 'c', done: false }
iter.next() // { value: undefined, done: true }
自已定义的类满足遍历器
class RangeIterator {
constructor(start, stop) {
this.value = start;
this.stop = stop;
}
[Symbol.iterator]() { return this; }
next() {
var value = this.value;
if (value < this.stop) {
this.value++;
return {done: false, value: value};
} else {
return {done: true, value: undefined};
}
}
}
function range(start, stop) {
return new RangeIterator(start, stop);
}
for (var value of range(0, 3)) {
console.log(value);
}
在 generator 函数中 每次遍历返回一个 yield, 但是如果出现 yield* 后面跟的是一个可遍历的结构,它会调用该结构的遍历器接口。
let generator = function* () {
yield 1;
yield* [2,3,4]; //use an iterable, is looped, and added as yields
yield 5;
};
var iterator = generator();
iterator.next() // { value: 1, done: false }
iterator.next() // { value: 2, done: false }
iterator.next() // { value: 3, done: false }
iterator.next() // { value: 4, done: false }
iterator.next() // { value: 5, done: false }
iterator.next() // { value: undefined, done: true }
var myIterable = {};
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
[...myIterable] // [1, 2, 3]
// 或者采用下面的简洁写法
let obj = {
* [Symbol.iterator]() {
yield 'hello';
yield 'world';
}
};
for (let x of obj) {
console.log(x);
}
// hello
// world
可以使用for...of循环遍历器
可以用for...of遍历集合 不能遍历对象
Generator 函数
Generator函数有多种理解角度。从语法上,首先可以把它理解成一个函数的内部状态的遍历器(也就是说,Generator函数是一个状态机)。它每调用一次,就进入下一个内部状态。Generator函数可以控制内部状态的变化,依次遍历这些状态。
形式上,Generator函数是一个普通函数,但是有两个特征。一是,function命令与函数名之间有一个星号;二是,函数体内部使用yield语句,定义遍历器的每个成员,即不同的内部状态(yield语句在英语里的意思就是“产出”)。
任意一个对象的Symbol.iterator属性,等于该对象的遍历器函数,调用该函数会返回该对象的一个遍历器。
yield
next的参数就是yield的返回值
function* foo(x) {
var y = 2 * (yield (x + 1));
var z = yield (y / 3);
return (x + y + z);
}
var it = foo(5);
it.next()
// { value:6, done:false }
it.next(12)
// { value:8, done:false }
it.next(13)
// { value:42, done:true }
内部捕获异常
var g = function* () {
while (true) {
try {
yield;
} catch (e) {
if (e != 'a') throw e;
console.log('内部捕获', e);
}
}
};
var i = g();
i.next();
try {
i.throw('a');
i.throw('b');
} catch (e) {
console.log('外部捕获', e);
}
// 内部捕获 a
// 外部捕获 b
yield*语句
如果yield命令后面跟的是一个遍历器,需要在yield命令后面加上星号,表明它返回的是一个遍历器。这被称为yield*语句。