async 异步操作
async 函数,它就是 Generator 函数的 语法糖
作用:使得异步操作更加方便
异步操作是JavaScript编程的麻烦事,很多人认为async函数是异步编程的解决方案
- 凡是在前面添加了async的函数在执行后都会自动返回一个Promise对象
async function test() {
}
let result = test()
console.log(result) //即便代码里test函数什么都没返回,我们依然打出了Promise对象
- await必须在async函数里使用,不能单独使用
- await的作用之一就是获取后面Promise对象成功状态传递出来的参数传给 then 函数。
async function f() {
/*
** 如果 await 命令后面的不是一个Promise实例对象,
** await 命令会自动把await后面转为一个Promise实例对象
*/
return await 'hello async';
}
// 因为返回的是一个Promise实例对象,所以可以用链式编程
f().then(v => {console.log(v)}).catch(e => {console.log(e)}); //输出 hello async
- 如果 async 函数中有多个 await , 那么 then 函数 会等待所有的 await 指令运行完才去执行
async function f(){
let s = await 'hello world'
let data = await s.split('');
return data;
}
f().then(v => {console.log(v)}).catch(e => {console.log(e)});
- 任何一个
await
语句后面的 Promise 对象变为reject
状态,那么整个async
函数都会中断执行。
async function f(){
await Promise.reject('出错了');
await Promise.resolve('hello');
}
f().then(v => {console.log(v)}).catch(e => {console.log(e)}); //输出 出错了
/*
** async函数f执行后,await后面的 Promise 对象会抛出一个错误对象,
** 变成了 reject 状态,catch方法的回调函数被调用
*/
async function f2() {
await new Promise(function (resolve, reject) {
// 抛出一个错误对象
throw new Error('出错了');
});
}
f2().then(v => console.log(v)).catch(e => console.log(e))
// Error:出错了
async 的错误处理 try...catch
针对上诉遇到 reject
状态,就中断执行的问题,可以通过 try...catch 代码块解决
async function f() {
try {
await Promise.reject('出错了');
} catch (error){
}
return await Promise.resolve('hello');
});
}
f2().then(v => console.log(v)).catch(e => console.log(e)) // 输出 hello
class 类的用法
// es5
/*
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayName = function() {
return this.sayName;
}
let p = new Person('牛肉粉',18);
console.log(p);
*/
// es6
class Person {
// 实例化的时候会立即被调用
constructor(name, age){
this.name = name;
this.age = age;
}
//等同于Person.prototype = function sayName(){}
sayName(){
return this.name;
}
sayAge(){
return this.age;
}
}
// 小技巧:通过 Objec.assign() 方法(详见对象的扩展功能)一次性向类中添加多个方法
/*
Object.assign(Person.prototype, {
sayName(){
return this.name;
}
sayAge(){
return this.age;
}
})
*/
let p = new Person('牛肉粉',18);
console.log(p);
p.sayName();
p.sayAge();
- 类的继承
class Animal {
// 实例化的时候会立即被调用
constructor(name, age){
this.name = name;
this.age = age;
}
sayName(){
return this.name;
}
sayAge(){
return this.age;
}
}
class Dog extends Animal{
constructor(name, age, color){
// 如果 子类 继承了 父类,且 子类 中写了构造器,则 子类 构造器的 super 必须要调用
super(name, age); // 等同于 Animal.call(this,name,age); 继承父类的属性
this.color = color;
}
// 子类自己的方法
sayColor(){
return `${this.name}是${this.age}岁了,它的颜色是${this.color}`;
}
// 重写父类的方法
sayName(){
// super 相同于 Animal
return this.name + super.sayAge + this.color;
}
}
let d1 = new Dog('小黄', 28, 'red');
console.log(d1.sayAge()); // 调用继承父类的方法
console.log(d1.sayColor()); // 调用子类自己的方法
console.log(d1.sayName()); // 调用重写父类的方法
ES6 module(模块化)
历史上,JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。其他语言都有这项功能,比如 Ruby 的require、Python 的import,甚至就连 CSS 都有@import,但是 JavaScript 任何这方面的支持都没有,这对开发大型的、复杂的项目形成了巨大障碍
在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。
ES6 模块功能主要有两个命令构成:export 和 import
export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量
//module/index.js
export const name = '张三';
export const age = 18;
export const sayName = function() {
console.log(fristName);
}
//也可以这样
const name = '张三';
const age = 18;
const sayName = function() {
console.log(fristName);
}
export {name, age, sayName}
//main.js
import {name, age, sayName} from './modules/index.js';//解构赋值 {name, age, sayName}
使用export default
命令为模块指定默认输出,在其它模块加载该模块时,import
命令可以为该匿名函数指定任意名字
//export-default.js
export default function(){
console.log('foo');
}
//或者写成
function foo() {
console.log('foo');
}
export default foo;
//import-default.js
import customName from './export-default.js'
customNmae();//foo
如果想在一条import语句中,同时输入默认方法(default)和其他接口(非default),可以写成下面这样
//export-default.js
export default function(){
console.log('foo');
}
export function add(){
console.log('add')
}
import customName,{add} from 'export-default.js'
// 方式二 * 代表所有属性和方法 as 代表重命名
import * as f from 'export-default.js'
console.log(f); // 输出一个 模块, 里面保存了 export 传过来的所有属性和方法
console.log(f.default);
export default
也可以用来输出类。
// MyClass.js
export default class Person{ ... }
// main.js
import Person from 'MyClass';
let o = new Person();