es6学习(下)

一.Promise对象

Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.all([p1, p2, p3]);

上面代码中,Promise.all()方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例,如果不是,就会先调用下面讲到的Promise.resolve方法,将参数转为 Promise 实例,再进一步处理。另外,Promise.all()方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。
p的状态由p1、p2、p3决定,分成两种情况。
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
下面是一个具体的例子。

// 生成一个Promise对象的数组const promises = [2, 3, 5, 7, 11, 13].map(function (id) {
return getJSON('/post/' + id + ".json");});

Promise.all(promises).then(function (posts) {
  // ...}).catch(function(reason){
  // ...});

上面代码中,promises是包含 6 个 Promise 实例的数组,只有这 6 个实例的 状态都变成fulfilled,或者其中有一个变为rejected,才会调用Promise.all方法后 面的回调函数。

二.Async函数:使得异步操作更加方便

async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。
Async和await命令后面,可以是promise对象和原始类型的值(数值,字符串和布尔值,但这时会自动转成立即resolved的promise对象)。
async函数的返回值是promise对象,可以用then方法指定下一步的操作,进一步说,async函数完全可以看作多个异步操作,包装成一个promise对象,而await命令就是内部then命令的语法糖。
1.基本语法
async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
async函数返回一个 Promise 对象,async函数内部return语句返回的值,会成为then方法回调函数的参数。

async function f() {
return 'hello world';}
f().then(v => console.log(v))   // "hello world"

async函数内部抛出错误,会导致返回的 Promise 对象变为reject状态。抛出的错误对象会被catch方法回调函数接收到。

async function f() {
  throw new Error('出错了');}
f().then(
  v => console.log(v),
  e => console.log(e))   // Error: 出错了

async函数返回的 Promise 对象,必须等到内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数。
正常情况下,await命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。

async function f() {
  // 等同于  return 123; 
	return await 123;
}
f().then(v => console.log(v))   // 123

另一种情况是,await命令后面是一个thenable对象(即定义了then方法的对象),那么await会将其等同于 Promise 对象。

class Sleep {
  constructor(timeout) {
    this.timeout = timeout;
  }
  then(resolve, reject) {
    const startTime = Date.now();
    setTimeout(
      () => resolve(Date.now() - startTime),
      this.timeout
    );
  }}
(async () => {
  const sleepTime = await new Sleep(1000);
  console.log(sleepTime);})();
// 1000

await命令后面的 Promise 对象如果变为reject状态,则reject的参数会被catch方法的回调函数接收到。

async function f() {
  await Promise.reject('出错了');}
f().then(v => console.log(v)).catch(e => console.log(e))  // 出错了

任何一个await语句后面的promise对象变为reject状态,那么整个async函数都会中断执行。
有时我们希望即使前一个异步操作失败,也不要中断后面的异步操作,这时可以将第一个await放在try…catch结构里面,这样不管这个异步操作是否成功,第二个await都会执行。
另一种方法是await后面的promise对象在跟一个catch方法,处理前面可能出现的错误。
多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。

let foo = await getFoo();
let bar = await getBar();

上面代码中,getFoo和getBar是两个独立的异步操作(即互不依赖),被写成继发关系。这样比较耗时,因为只有getFoo完成以后,才会执行getBar,完全可以让它们同时触发。
await命令只能用在async函数之中,如果用在普通函数,就会报错。
如果确实希望多个请求并发执行,可以使用Promise.all方法。当三个请求都会resolved时,下面两种写法效果相同。

三.class的基本语法

Es6可以看作只是一个语法糖,它的绝大部分功能,es5都可以做到,新的class写法只是让对象原型的写法更加清晰,更像面向对象编程的语法而已。

Class  Point{              //定义一个类
	Constructor(x, y){       //类的构造函数
		This.x = x;			//this代表实例对象
		This.y = y;
	}
	toString(){           //类中的方法
		Return (+ this.x +,+ this.y +);
	}
}
Class ColorPoint extends Point{  //子类继承父类:extends关键字实现类的继承
	Constructor(x,y,color){
		Super(x, y);     //super作为函数调用,代表父类构造函数,只能放在子类构造函数中,且只能放在第一句,但是返回的是子类的实例,因此super相当于Point.prototype.constructor.call(this)
		This.color = color;
	}
	toString() {
		Return this.color + ‘ ’ + super.toString(); //super当作一个对象来使用,这时super在普通方法之中,指向Point.prototype,	所以super.toString()就相当于Point.prototype.toString()。由于super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的。
	}
}
Let colorPoint1  =  new  Point(3,4);   //类的实例对象

四.module的语法
Es6模块: import { stat, exits, readFile} from ‘fs’;
Es6模块自动采用严格模式,不管你有没有在模块头部加上”use strict”
模块功能主要由两个命令构成: export和import。 export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

  1. 一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。下面是一个 JS 文件,里面使用export命令输出变量。
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;

上面的写法可以写成(推荐使用这种2方法):

var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export { firstName, lastName, year };

Export除了可以输出变量,还可以输出类或者函数
Export function multiply(x, y){ return x*y; };
通常情况下,export输出的变量就是本来的名字,但是可以使用as关键字重命名:

Function v1() {......}
Function v2() {......}
Export { v1 as  v11, v2 as v22, v2 as v33};

上面代码使用as关键字,重命名了函数v1和v2的对外接口,重命名后,v2可以用不同的名字输出两次,注意写法规范,否则会报错,下面是正确的写法:

//写法一: export var m = 1;
//写法二: var m = 1;  export  {m};
//写法三: var n= 1;  export {n as m};
//导出函数写法一:export function  f() {};
//导出函数写法二: function  f() {}   export {f}; 

export命令可以出现在模块的任何位置,只要处于模块顶层就可以,如果处于块级作用域内,就会报错,import命令也是如此。
2.使用export命令定义了模块的对外接口外,其他js文件就可以通过import命令加载这个模块。

Import { firstname, lastname, year } from./profile.js’;
Function setname(ele) {
	Ele.textContent = firstname+ ‘ ’+lastname;
}

Import大括号里面的变量名,必须与被导入模块profile.js对外接口的名称相同。要想为输入的变量重新取一个名字,import命令要用as关键字,将输入的变量重命名。
Import { lastname as name } from ‘./profile.js’
不能对import加载过来的变量重新赋值,但是如果加载过来的是个对象,则可采用对象名.属性名的方式改写。
From指定模块文件的位置,可以是相对路径,也可以是绝对路径,.js后缀可以省略。
import命令具有提升效果,会提升到整个模块的头部,首先执行。
import是静态执行,所以不能使用表达式和变量,也不能写在if这些块级作用域中。

import { foo } from 'my_module';
import { bar } from 'my_module';
// 等同于import { foo, bar } from 'my_module';

3.从前面的例子可以看出,使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。
为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。

// export-default.js
export default function () {
  console.log('foo');
}

上面代码是一个模块文件export-default.js,它的默认输出是一个函数。
其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。

// import-default.js
import customName from './export-default';
customName(); // 'foo'

上面代码的import命令,可以用任意名称指向export-default.js输出的方法,这时就不需要知道原模块输出的函数名。需要注意的是,这时import命令后面,不使用大括号。
下面比较一下默认输出和正常输出。

// 第一组
export default function crc32() { // 输出  // ...}
import crc32 from 'crc32'; // 输入
// 第二组
export function crc32() { // 输出  // ...};
import {crc32} from 'crc32'; // 输入

上面代码的两组写法,第一组是使用export default时,对应的import语句不需要使用大括号;第二组是不使用export default时,对应的import语句需要使用大括号。
export default命令用于指定模块的默认输出。显然,一个模块只能有一个默认输出,因此export default命令只能使用一次。所以,import命令后面才不用加大括号,因为只可能唯一对应export default命令。
正是因为export default命令其实只是输出一个叫做default的变量,所以它后面不能跟变量声明语句。

// 正确  export var a = 1;
// 正确  var a = 1;   export default a;
// 错误  export default var a = 1;

4.export和import的复合写法
如果在一个模块之中,先输入后输出同一个模块,import语句可以与export语句写在一起。

export { foo, bar } from 'my_module';
// 可以简单理解为import { foo, bar } from 'my_module';
export { foo, bar };
具名接口改为默认接口的写法如下。
export { es6 as default } from './someModule';
// 等同于
import { es6 } from './someModule';
export default es6;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

the_lower

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值