ES6 笔记
解构赋值 Destructuring
从数组或对象中提取值,对变量进行赋值。以匹配结构形式,将数组或变量对应位置的值赋予对应结构位置的变量。 等号右边,必须是可遍历的数据结构。
let [a, ...b] = [1, 2, 3, 4]
a // 1
b // [2, 3, 4]
// 变量替换
let a = 1, b = 10;
[a, b] = [b, a];
a // 10
b // 1
// 对象结构
let {baz, foo} = {baz: 'aaa', foo: 'bbb'};
baz // aaa
foo // bbb
const original = { a: 1, b: 2 };
const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }
const { a, ...noA } = copy; // noA => { b: 2, c: 3 }
Symbol
Symbol 是 ES6 扩展的第七种数据类型(另六种 undefined、null、Boolean、String、Number、Object)。 Symbol 每次调用生成一个独一无二的标识符,此类型不能隐式转换为字符串(不能与字符串类型相加),可显示转换(String 函数)。对象的 Symbol 类型的属性不能通过 Object.keys 或 for .. in 的方式遍历到,需 Object.getOwnPropertySymbols 获取。
let a = Symbol();
let b = Symbol();
a === b // false
// 可传人参数,当作 Symbol 的理解信息
let s1 = Symbol('foo');
let s2 = Symbol('bar');
console.log(s1 );
// Symbol(foo)
// 作为对象属性
let attr = Symbol();
let obj[attr] = 'Hello';
如何重复使用一个值
let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');
s1 === s2 // true
Symbol.iterator 将数组转化为一个迭代器
let arr = [1, 2, 3, 4, 5];
let it = arr[Symbol.iterator]();
it.next() // {value: 1, done: false}
it.next() // {value: 2, done: false}
Promise
Promise 是一种异步编程解决方案,作为容器组合了异步函数及其回调。异步函数作为参数传递给 Promise 构造函数完成实例化,同时 Promise 对象会提供两个可改变自己状态(成功 fulfilled 或失败 rejected)的方法(resolve 和 reject)给异步函数,一旦异步函数改变状态,Promise 会自动调用通过 then 、catch 等方法附加在其上的回调函数。
Promise 对象的特点
Promise 是一个 micro task,一旦新建就会立即执行,此时处于 pending 状态,无法取消,只有异步操作的结果可以改变对象为 fulfiled 或 rejected。
状态改变后,不再变化。此时再通过 then 向对象添加回调函数,会立即得到结果,与事件不同的时,事件错过了,再此添加监听,无法收到过去的事件。
使用流程
- 创建实例
- then 方法增加指定回调
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
promise.then(function(value) {
// success
}, function(error) {
// failure
});
示例
const promise = new Promise(function(resolve, reject){
console.log('first info');
setTimeout(function() {
resolve('OK');
}, 1000);
});
promise.then(function(value){
console.log('in then get: ' + value);
});
console.log('wait for ...');
// first info
// wait for ...
// in then get: OK
then 方法
then 方法用于为 Promise 实例添加状态改变时的回调函数,其定义在 Promise.prototype 上。then 方法接收的第一个参数为状态 resolve 后的回调函数,第二个参数可选,为状态 reject 后的回调函数。 then 方法调用结束后会返回一个新的 Promise 实例,因此可以采用链式写法,即 then 方法后面再调用另一个 then 方法。 如果上一个 then 方法接收的回调函数返回的是不是一个 Promise 对象,返回值将会作为结果传递给第二个回调函数。 内部错误不会抛出,catch 会吃掉内部产生的错误。
Promise.all([])
接收一个 promise 对象数组返回一个新的 promise 对象,所有的 promise 都 resolve 以后才会 resolve,否则 reject 如果有 promise reject 被捕获,仍会认为其 fulfiled,最后运行 resolve。
Promise.resolve() 将现有参数转化为 promise 对象
Promise.resolve('foo')
// 等价于
new Promise(resolve => resolve('foo'))
done 和 finally 区别,done 穿进去的函数不一定被执行
Generator
Generator 是一个状态机,封装了多个内部状态。函数调用后会返回一个遍历器对象,调用遍历器的next() 方法可以依次遍历函数的每个状态,每调用一次返回一个有 value 和 done(Boolean类型)的对象。 声明使用 function * ,定义内部状态使用 yeild 关键字修饰表达式, return 的结果也是一种状态。 每调用一次 next,内部指针就从函数头或上一次 yield 下来,直到遇到下一个 yield 或 return。
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
hw.next().value
- next 可传入参数,作为函数内部 yield语句的返回值
- for…of循环可以自动遍历 Generator 函数时生成的Iterator对象,且此时不再需要调用next方法。
- return 后的值不会被遍历
- next、throw、return 都可恢复执行
- yield * 用来在一个 Generator 函数内部执行另一个 Generator 函数
async await ES2017
实现异步操作的方法,执行到 await 函数会交出执行权,等到结果返回后,继续向下执行。
async function fetchData() {
const data1 = await fetch('file1');
const data2 = await fetch('file2');
}
- await 接收一个 Promise 对象,或者原始类型的值
- 函数的返回值是 Promise ,因此可以再通过 then 函数,附加其它操作。
- 函数的返回 Promise,需等到内部的所有 await 返回,或遇到 return
- Generator 函数的语法糖,但是自带执行器,省去了 Generator 调用 next 的过程。
ES6 class
类属性的实例化写在 constructor 构造函数中,方法写在类体内,不需要 function 关键字修饰。当前 ES6 不支持私有方法和私有属性。变通的方法是,将函数与类声明在同一文件中,仅供类使用。
class Bar {
constructor(props) {
}
method() {
}
}
ES6的类相当 ES5 构造函数方法创建对象的语法糖。
Bar === Bar.prototype.constructor // true
typeof Bar // function
静态方法
使用关键字static修饰的方法为类方法,可通过类调用,可被子类继承。
class Bar {
static foo() {
console.log('in foo');
}
}
Bar.foo();
// in foo
类的继承
ES6 采用关键字 extends 继承父类,子类的如果声明了构造函数(没有声明会被默认添加,任何子类都有 constructor 方法属性)中必须调用 super(),否则新建实例时会报错。
class Point { /* ... */ }
class ColorPoint extends Point {
constructor() {
}
}
let cp = new ColorPoint(); // ReferenceError
ES6 的子类没有自己的 this 对象,而是继承父类的 this 对象,然后对其进行加工。如果不调用 super 方法,子类就得不到 this 对象。ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。ES6 的继承机制完全不同,实质是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this。