zl程序教程

您现在的位置是:首页 >  后端

当前栏目

那些必会用到的 ES6 精粹(下)

ES6 那些 必会 用到 精粹
2023-09-27 14:25:58 时间
10. Promise 对象


Promise 是异步编程的一种解决方案。


Promise 对象代表一个异步操作 有三种状态 pending 进行中 、fulfilled 已成功 和rejected 已失败 。


Promise 对象的状态改变 只有两种可能 从 pending 变为 fulfilled 和从 pending 变为

rejected。只要这两种情况发生 状态就凝固了 不会再变了 会一直保持这个结果 这时就称为 resolved 已定型


const someAsyncThing function(flag) {

 return new Promise(function(resolve, reject) {

 if(flag){

 resolve( ok 

 }else{

 reject( error )

someAsyncThing(true).then((data) {

 console.log( data: ,data); // 输出 ok 

}).catch((error) {

 console.log( error: , error); // 不执行

someAsyncThing(false).then((data) {

 console.log( data: ,data); // 不执行

}).catch((error) {

 console.log( error: , error); // 输出 error 

})


上面代码中 someAsyncThing 函数成功返回 ‘OK’, 失败返回 ‘error’, 只有失败时才会被 catch 捕捉到。


最简单实现


// 发起异步请求

 fetch( /api/todos )

 .then(res res.json())

 .then(data ({ data }))

 .catch(err ({ err }));


来看一道有意思的面试题


setTimeout(function() {

 console.log(1)

}, 0);

new Promise(function executor(resolve) {

 console.log(2);

 for( var i i 10000 ; i ) {

 i 9999 resolve();

 console.log(3);

}).then(function() {

 console.log(4);

console.log(5);


这道题应该考察 JavaScript 的运行机制的。


首先先碰到一个 setTimeout 于是会先设置一个定时 在定时结束后将传递这个函数放到任务队列里面 因此开始肯定不会输出 1 。


然后是一个 Promise 里面的函数是直接执行的 因此应该直接输出 2 3 。


然后 Promise 的 then 应当会放到当前 tick 的最后 但是还是在当前 tick 中。

因此 应当先输出 5 然后再输出 4 。


最后在到下一个 tick 就是 1 。


答案  “2 3 5 4 1”


11. async 函数


ES2017 标准引入了 async 函数 使得异步操作变得更加方便。


async 函数的使用方式 直接在普通函数前面加上 async 表示这是一个异步函数 在要异步执行的语句前面加上 await 表示后面的表达式需要等待。async 是 Generator 的语法糖

async 函数内部 return 语句返回的值 会成为 then 方法回调函数的参数。


async function f() {

 return hello world 

f().then(v console.log(v))

// hello world 


上面代码中 函数 f 内部 return 命令返回的值 会被 then 方法回调函数接收到。

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


async function f() {

 throw new Error( 出错了 

f().then(

 result console.log(result),

 error console.log(error)

// Error: 出错了


async 函数返回的 Promise 对象 必须等到内部所有 await 命令后面的 Promise 对象执行完 才会发生状态改变 除非遇到 return 语句或者抛出错误。也就是说 只有 async 函数内部的异步操作执行完 才会执行 then 方法指定的回调函数。


下面是一个例子:


async function getTitle(url) {

 let response await fetch(url);

 let html await response.text();

 return html.match(/ title ([\s\S] ) \/title /i)[1];

getTitle( https://tc39.github.io/ecma262/ ).then(console.log( 完成 ))

// ECMAScript 2017 Language Specification 


上面代码中 函数 getTitle 内部有三个操作 抓取网页、取出文本、匹配页面标题。只有这三个操作全部完成 才会执行 then 方法里面的 console.log。


在 vue 中 我们可能要先获取 token 之后再用 token 来请求用户数据什么的 可以这样子用


methods:{

 getToken() {

 return new Promise((resolve, reject) {

 this.$http.post( /token )

 .then(res {

 if (res.data.code 200) {

 resolve(res.data.data)

 } else {

 reject()

 .catch(error {

 console.error(error);

 getUserInfo(token) {

 return new Promise((resolve, reject) {

 this.$http.post( /userInfo ,{

 token: token

 .then(res {

 if (res.data.code 200) {

 resolve(res.data.data)

 } else {

 reject()

 .catch(error {

 console.error(error);

 async initData() {

 let token await this.getToken()

 this.userInfo this.getUserInfo(token)

}


12. import 和 export


import 导入模块、export 导出模块

// example2.js // 导出默认, 有且只有一个默认

export default const example2 {

 name : my name ,

 age : my age ,

 getName function(){ return my name }

//全部导入 // 名字可以修改

import people from ./example2.js 

-------------------我是一条华丽的分界线---------------------------

// example1.js // 部分导出

export let name my name 

export let age my age 

export let getName function(){ return my name }

// 导入部分 // 名字必须和 定义的名字一样。

import {name, age} from ./example1.js 

//有一种特殊情况 即允许你将整个模块当作单一对象进行导入

//该模块的所有导出都会作为对象的属性存在

import * as example from ./example1.js 

console.log(example.name)

console.log(example.age)

console.log(example.getName())

-------------------我是一条华丽的分界线---------------------------

// example3.js // 有导出默认, 有且只有一个默认 // 又有部分导出

export default const example3 {

 birthday : 2018 09 20 

export let name my name 

export let age my age 

export let getName function(){ return my name }

// 导入默认与部分

import example3, {name, age} from ./example1.js 


总结


1.当用 export default people 导出时 就用 import people 导入 不带大括号 

2.一个文件里 有且只能有一个 export default。但可以有多个 export。

3.当用 export name 时 就用 import { name }导入 记得带上大括号 

4.当一个文件里 既有一个 export default people, 又有多个 export name 或者 export age 时 导入就用 import people, { name, age } 

5.当一个文件里出现 n 多个 export 导出很多模块 导入时除了一个一个导入 也可以用 import * as example


13. Class


对于 Class 小汪用在 react 中较多。


13.1基本用法


//定义类

class FunSum {

 constructor(x, y) {

 this.x 

 this.y 

 sum() {

 console.log( this.x this.y )

// 使用的时候 也是直接对类使用new命令 跟构造函数的用法完全一致。

let f new FunSum(10, 20);

f.sum() // 30


13.2 继承


class ColorPoint extends Point {

 constructor(x, y, color) {

 super(x, y); // 调用父类的constructor(x, y)

 this.color color;

 toString() {

 return this.color super.toString(); // 调用父类的toString()

}


上面代码中 constructor 方法和 toString 方法之中 都出现了super关键字 它在这里表示父类的构造函数 用来新建父类的 this 对象。


子类必须在 constructor 方法中调用 super 方法 否则新建实例时会报错。这是因为子类自己的 this 对象 必须先通过父类的构造函数完成塑造 得到与父类同样的实例属性和方法 然后再对其进行加工 加上子类自己的实例属性和方法。如果不调用 super 方法 子类就得不到 this 对象。


class Point { /* ... */ }

class ColorPoint extends Point {

 constructor() {

let cp new ColorPoint(); // ReferenceError


上面代码中 ColorPoint 继承了父类 Point 但是它的构造函数没有调用 super 方法 导致新建实例时报错。


一篇文章带你学会整个ES6 ES 全称 EcmaScript,是脚本语言的 规范 ,而平时经常编写的 JavaScript ,是 EcmsScript 的 一种实现 ,所以 ES 新特性其实是指 JavaScript 的新特性 。
浅谈一下ES6的提升 es6的提升 在es6之前,我们定义定义变量的时候,只能使用var关键字来定变量,这样有一个问题,var定义的变量会成为全局变量。