ES6

72 阅读5分钟
1、ES6模块化

Node遵循的commonJS规范,是服务端使用的;开发者社区提供了AMD、CMD在浏览器端使用。现在ES6模块化规范是统一了浏览器端与服务器端通用的模块化开发规范,取代了AMD、CMD。

1.1 默认导出与导入
export default {
    //变量或者方法名
}
​
import dddd from 'XXXX'

注意:默认导出只能使用一次;默认导入的名字 dddd 可以是任意合法的名字。

1.2 按需导出与导入
export let n1 = 1
export let n2 ='123'
export function fun1(){}
​
import {n1, fun1} from 'XXX'

注意:

  • 按需导出可以使用多次,按需导入的名字 必须与按需导出的名字 保持一致;
  • 按需导入的时候可以通过as关键字重命名
  • 按需导入和默认导入可以配合使用,import dddd,{n1,n2,fun1} from 'XXXX' 这里dddd就是默认导出的,花括号里面的是按需导出的。
1.3 直接导入并执行代码

如果只是单纯地执行某个模块中的代码,并不需要得到模块中向外共享的成员。此时,可以直接导入并执行模块代码

// 某个模块 XXXX
console.log(10)
​
import 'XXXXXX'

启用ES6模块化支持:在package.json中声明"type":"module"

2、Promise相关
2.1 回调地狱,回调嵌套
2.2 Promise构造函数
  1. let p = new Promise() //实例化Promise对象
  2. .then()方法是Promise原型上面的方法,可以预处理成功和失败,成功回调和失败回调(可选的)
  3. .catch()方法捕获错误,放在最后面捕获前面所有异常,放在.then前面捕获这一个操作的异常且由于错误已经被catch不影响后续.then的正常执行。
2.3 Promise的使用场景
  1. 网络请求
  2. 有顺序先后要求的操作,比如先读取A文件成功后才读取B文件。
  3. Promise.all( [..., ..., ..., ...] ).then((n1,n2,n3)=>{...})可以并行多个异步操作。等待所有异步执行完毕
  4. Promise.race([a,b,c]).then(res=>{...}) 任意一个异步执行成功就结束,是赛跑机制
2.4 基于Promise封装异步方法

new Promise()只是创建了一个形式上的异步操作;如果想要创建具体的异步操作,则需要在new Promise()构造函数期间,传递一个function函数,将具体的异步操作定义到function函数内部。示例代码如下:

function getFile(fpath){
    // resolve形参对应成功的回调函数,reject形参对应失败的回调函数
    return new Promise(function(resolve,reject){ 
        fs.readFile(fpath,'utf-8',(err,dataStr)=>{ 
            if(err) return reject(err)
            resolve(dataStr)
        })
    })
}
​
// 通过.then()指定的成功和失败的回调函数,可以在function的形参中进行接收
// getFile('XXXX').then(成功的回调函数,失败的回调函数)
getFile('XXX').then((res)=>{...},(err)=>{...})
3、async/await

async/await 是ES8引入的新语法,用来简化Promise异步操作;在async/await出现之前,开发者只能通过链式.then()的方式处理异步操作。

当一个操作的返回值是一个Promise就可以通过await 修饰拿到返回的值;而不用.then(res)去拿;简化了操作

注意事项:

  1. 如果function中使用了await,则function必须被async修饰
  2. 在async方法中,第一个await之前的代码会同步执行,await之后的代码会异步执行
console.log('A')
async function getAllfiles(){
    console.log('B')
    // 第一个await 开始异步了;主线程退出这个函数,等到同步任务执行完后再继续执行异步任务。
    const r1 = await getfile('XXX') 
    const r2 = await getfile('XXX')
    const r3 = await getfile('XXX')
    console.log(r1,r2,r3)
    console.log('D')
}
getAllfiles()
console.log('C')
//最终结果 
A
B
C
r1.r2.r3
D
4、EventLoop 事件循环
  1. 同步任务有js主线程按次序执行

  2. 异步任务委托给宿主环境(nodejs或者浏览器)执行

  3. 已完成的异步任务对应的回调函数,会被加入到任务队列中等待执行

  4. js主线程执行完同步任务后,会读取任务队列中的回调函数,次序执行

  5. js主线程不断重复上面的第四步

    console.log('A')
    getfile(XXX).then(res=>{
        console.log('B')
    })
    setTimeout(()=>{ // 因为等待0秒,就是异步里面的最先的
        console.log('C')
    },0)
    console.log('D')
    // adcb
    
5、宏任务和微任务

javaScript把异步任务又做了进一步的划分,异步任务又分为两类,分别是

1、宏任务
  • 异步Ajax请求
  • setTimeout & setInterval
  • 文件操作
  • UI交互事件:onclick等
  • postMessage
2、微任务
  • Promise.then .catch .finally
  • process.nextTick
  • MutationObserver 监听DOM变化
  • 其他微任务
3、执行顺序

交替执行。每一个宏任务执行完之后,都会检查是否存在待执行的微任务,如果有,则执行完所以微任务之后,再继续执行下一个宏任务。

4、面试题
setTimeout(function(){ //1.宏任务
    console.log('1')
})
new Promise(function(resolve){ //new Promise构造函数是同步任务,传入的函数会立即执行。
    console.log('2')
    resolve()
}).then(function(){  // 微任务
    console.log('3')
})
console.log('4')   // 同步任务
//先肯定是按顺序执行同步任务,2 4
//然后执行微任务,再执行宏任务 所以3 1
console.log('1')
setTimeout(function(){
    console.log('2')
    new Promise(function(resolv){
        console.log('3')
        resolve()
    }).then(function(){
        console.log('4')
    })
})
new Promise(function(resolv){
    console.log('5')
    resolve()
}).then(function(){
    console.log('6')
})
setTimeout(function(){
    console.log('7')
    new Promise(function(resolv){
        console.log('8')
        resolve()
    }).then(function(){
        console.log('9')
    })
})
// 15 6 234 789 这里先执行两个同步,然后一个微任务,最后依次两个宏任务(宏任务里面有微任务要等待微任务执行完,才会执行下一个宏任务)