Featured image of post Es6

Es6

了解ECMAScript

什么是 ECMAScript?

官方定义: ECMAScript 是定义脚本语言的规范, 而 JavaScript 是遵循 ECMAScript 规范实现的一种编程语言

ES6 和 JavaScript 有什么区别?

ES6(ECMAScript 2015)是ECMAScript规范的第六个版本,而JavaScript是基于ECMAScript规范实现的编程语言,ES6可以被看作是 JavaScript 的一个重要的版本更新

ES6(ECMAScript 2015)新特性

  • let和const关键字用于声明块级作用域变量和常量
  • 箭头函数表达式
  • 类定义和继承
  • 模板字符串
  • 解构赋值
  • 函数参数默认值
  • Promise 异步编程
  • 异步函数 async/await
  • Map 和 Set 数据结构
  • 模块化 import 和 export

变量和常量

变量

字符串类型 string

let name = "张三"

数值类型 number

let num = 20
let num = 25.3

先声明后赋值

let user
user = "lihua"

常量

const PI = 3.14

两者区别

变量可以重新赋值,常量不可以

注意

ES6不区分整型和浮点型, 所有数字都使用 number类型 来表示

数据类型

字符串类型 string

let name = "张三"

数值类型 number

let num = 20

布尔类型 boolean

let tv = true

对象 object

let user = {
	name: "张三",
	age: 18,
	gender: "男"
}

map: 用于存储 键值对有序集合,

let user = new Map([
  ["name", "张三"],
  ["age", 20],
  ["gender", "男"]
])
// typeof 仍显示对象
// Map相对于对象提供了更灵活、有序、高效的键值对存储和操作方式,当需要在大量键值对中快速查找或删除特定键值对时, Map比对象更高效
// Map提供了一些便捷的方法来操作键值对, 如: get()、set()、delete()
// Map提供了一些便捷的迭代方法, 如: forEach()、keys()、values()、entries()

set: 用于存储 无序且唯一 的值的集合

let number = new Set([1, 2, 3, 4, 5])

数组 array

let str = ["a","b","c","b"] 

函数 function

function add(a, b) {
	return a + b
}

类 class

class Person {
  // 有参构造函数
  constructor(username, userage) {
    this.name = username
    this.age = userage
  }
	// 类中方法
  info() {
    console.log("姓名", this.name, "年龄", this.age)
  }
}
	// 实例化
  const person = new Person("瑶瑶", 20)
  // 调用类中方法
  person.info()

对比 object、map、set、array

形式有序 or 无序重复 or 不重复数据类型
object{键值对,键值对…}有序键不要重复(键值对)复合(object)
map(需要new)new map ([ [键值对],[键值对]… ])有序键不要重复(键值对)复合(object)
set (需要new)new set([…, …])无序不重复…复合(object)
array[…, …]有序重复…复合(object)

函数

无参函数

function getWeb() {
	return "www.yyqsdjc.com"
}
console.log("网站", getWeb())

有参函数

function add(number) {
	return number + 10
}
console.log("add", add(20))

带默认值的函数

function getPage(page = 1) {
  return page
}
console.log("getPage - 默认值", getPage())
console.log("getPage", getPage(7))

匿名函数

通常被用作回调函数

let sub = function (x, y) { //函数赋值给了一个变量 sub, 函数本身并没有一个具名标识符
  return x - y
}
console.log("sub", sub(30, 5))

// 回调函数是一种在特定事件或条件发生时被调用的函数, 回调函数通常用于异步编程中,
// 比如 success 是 ajax 中的一个回调函数, 用于处理请求成功的结果

箭头函数

let plus = (a, b) => {
  return a + b
}
console.log("plus", plus(5, 10))

    

隐式返回

在函数体内只有一个表达式的情况下, 可以省略花括号 {} 和 return 关键字

let add = (a, b) => a + b
console.log("add", add(10, 20))

array数组

定义数组

let arr = [10, 11]
console.log("arr", arr)

push()尾部加

向数组 末尾添加 一个或多个元素, 并返回修改后数组的长度

let arrLength = arr.push(12,13)
console.log("arr", arr) //[10,11,12,13]

unshift()头部加

向数组 开头添加 一个或多个元素, 并返回修改后数组的长度

arrLength = arr.unshift(8,9)
console.log("arr", arr) //[8,9,10,11,12,13]

shift()头部删

删除数组中 **第一个 **元素, 并返回被删除元素

let delElement = arr.shift()
console.log("arr", arr) //[9, 10, 11, 12, 13]
console.log("delElement", delElement) //8

pop()尾部删

删除数组 最后一个 元素, 并返回被删除元素

delElement = arr.pop()
console.log("arr", arr) //[9, 10, 11, 12]
console.log("delElement", delElement) //13

splice()增加删除元素

index必需。规定从何处添加/删除元素。 该参数是开始插入和(或)删除的数组元素的下标,必须是数字。
howmany可选。规定应该删除多少元素。必须是数字,但可以是 “0”。 如果未规定此参数,则删除从 index 开始到原数组结尾的所有元素。
item1, …, itemX可选。要添加到数组的新元素

splice(“下标”,“个数”,“可选增加 可以多个”) 增加和删除 返回被删除的元素

let delArr = arr.splice(2, 2) // 在索引为2的位置,删除2个元素
console.log("arr", arr) //[9, 10]
console.log("delArr", delArr) //[11, 12]

let arr = [1,5,8,7,9];
let addArr = arr.splice(1,3,666,888);//在索引为1的位置,先删除3个元素,再增加2个元素
console.log("arr", arr) //[1,666,888,9]
console.log("addArr", addArr) //[5,8,7] 返回被删除的元素

reverse()倒序

let arr = [1,5,8,7,9];
arr.reverse();
console.log(arr); //[9,7,8,5,1]

sort()排序

默认情况下 sort() 方法使用字符串排序, 导致并没有按照数字大小排序

//数组中的元素按照首字母顺序排序
let arr2 = ['banana', 'apple', 'orange']
arr2.sort()
console.log("arr2", arr2) //['apple', 'banana', 'orange']

//数组中的元素按照数字排序 (a, b) => a - b
let arr3 = [5, 20, 13, 1, 4]
arr3.sort((a, b) => a - b)
console.log("arr3", arr3) //[1, 4, 5, 13, 20]

/*
   比较函数 (a, b) => a - b 接收两个参数 a 和 b, 用于比较这两个元素的大小, 返回 a - b 的结果决定了 sort() 方法的排序顺序
   若 a < b, 则 a - b 是一个负数, 表示 a 应该在 b 前面
   若 a = b, 则 a - b 是 0, 位置保持不变
   若 a > b, 则 a - b 是一个正数, 表示 a 应该在 b 后面
*/

filter()过滤

let arr4 = [10, 11, 12, 13, 14, 15]
let newArr = arr4.filter((value, index) => {
  return value > 12
})
console.log("newArr", newArr) //[13, 14, 15]

concat()合并

let arr5 = ["十六", "十七", "十八"]
//newArr = arr3.concat(arr5) //[1, 4, 5, 13, 20, '十六', '十七', '十八']
newArr = arr4.concat(arr5, 19, 20) //[10, 11, 12, 13, 14, 15, '十六', '十七', '十八', 19, 20]
console.log("newArr", newArr)

for(let…of…)遍历

for of 循环 map → [key,value]:解构

let user = new Map([
  ["name", "张三"],
  ["age", 20],
  ["gender", "男"]
]);
for(let [key,value] of user){
	console.log(key,value);
};
// name 张三
// age 20
// gender 男

for of 循环 数组

let arr6 = ["飞飞鱼", "www.yyqsdjc.cn", 567] //数组可以包含不同的数据类型
for (let item of arr6) {
	console.log(item)
}
// 飞飞鱼
// www.yyqsdjc.cn
// 567

foreach( (value,index) => {} )遍历

循环map

let user = new Map([
  ["name", "张三"],
  ["age", 20],
  ["gender", "男"]
]);
user.forEach((value,index)=> {
	console.log(index, value)
});
// name 张三
// age 20
// gender 男

循环数组

arr6.forEach((value,index) => {
	console.log(value,index)
})
// 飞飞鱼 0
// www.yyqsdjc.cn 1
// 567 2

Set集合

创建Set集合 new Set([ … , … ])

//let fruits = new Set() //创建一个空的Set集合
let fruits = new Set(['apple', 'orange', 'banana']) //创建一个包含初始值的Set集合

add()添加元素

fruits.add('mango')
//fruits.add("orange") //若该元素已经存在, 则不会重复添加, 因为 Set 中的元素必须唯一
console.log("fruits", fruits)

delete()删除元素

fruits.delete('banana')
console.log("fruits", fruits)

has()检查Set集合是否包含指定元素

console.log(fruits.has('banana'))

size获取Set集合的大小

console.log("fruits.size", fruits.size) // 注意size不是一个方法 不用加括号

Array.from(set) Set 转 数组

// 相当于去掉外层大括号
let fruits = new Set(['apple', ['aaa','bbb'], 'banana']);
let arr = Array.from(fruits)
console.log("arr", arr)

// ['apple', Array(2), 'banana']
// 0: "apple"
// 1: ['aaa', 'bbb']
// 2: "banana"

扩展运算符 [… set] Set 转 数组

// 相当于去掉外层大括号
let fruits = new Set(['apple', ['aaa','bbb'], 'banana']);
let arr2 = [...fruits]
console.log("arr2", arr2)

// ['apple', Array(2), 'banana']
// 0: "apple"
// 1: ['aaa', 'bbb']
// 2: "banana"

扩展运算符 可用于 展开可迭代对象 (如数组、字符串等)

// 字符串
let web = 'yyqsdjc'
let webArr = [...web]
['y', 'y', 'q', 's', 'd', 'j', 'c']

// 中文
let web = '飞飞鱼'
let webArr = [...web] //使用扩展运算符将 字符串 转换为 数组
console.log("webArr", webArr) //['飞', '飞', '鱼'] 

for(let…of…) 遍历

// 相当于去掉外层 大括号 和 中括号
let fruits = new Set(['apple', ['aaa','bbb'], 'banana']);
for (let item of fruits) {
  console.log(item)
};

// apple
// ['aaa', 'bbb']
// banana

forEach(value => {}) 遍历

// 相当于去掉外层 大括号 和 中括号
fruits.forEach(value => { // index 和 value 值一样
console.log(value)
})

// apple
// ['aaa', 'bbb']
// banana

clear()清空 Set

fruits.clear()
console.log("fruits.size", fruits.size)

数组去重

将 数组 转换为 Set集合 实现数组去重

let numberArr = [1, 2, 3, 3, 2, 1]
let numberSet = new Set(numberArr)
console.log(numberSet)

Map 集合

创建Map集合 new Map([ [],[]… ])

//let person = new Map() //创建一个空的Map集合
let person = new Map([
  ["name", "张三"],
  ["age", 20],
  ["gender", "男"]
])

set()添加元素

person.set('height', 175);
//在Map集合中, 每个键都是唯一的, 当使用相同的键再次调用 set() 方法时, 会替换原来键对应的值
person.set('age', 25)
console.log("person", person)

delete()删除元素

person.delete('gender')
console.log("person", person)

has()检查Map集合是否包含指定元素

console.log(person.has('gender'))

size获取Map集合的大小

console.log("person.size", person.size)

Array.from(map) Map 转 数组

// 相当于去掉外层大括号
let arr = Array.from(person)
console.log("arr", arr)

// [['name', '张三'],['age', 20],['gender', '男']]

扩展运算符[…map] Map 转 数组

// 相当于去掉外层大括号
let arr2 = [...person]
console.log("arr2", arr2)

// [['name', '张三'],['age', 20],['gender', '男']]

for(let…of…)遍历

//解构可以从数组或对象中提取值并赋给变量 //[key, value] 就是一种解构语法, 用于将 Map 集合中的键值对解构为 key 和 value 两个变量

// 相当于去掉外层 大括号 和 中括号
for (let [key, value] of person) {
  console.log(key, value)
}

// name 张三
// age 20
// gender 男

forEach((value, key) => {})遍历

// 相当于去掉外层 大括号 和 中括号
person.forEach((value, key) => {
  console.log("forEach", key, value)
})

// name 张三
// age 20
// gender 男

clear()清空 Map

person.clear()
console.log("person.size", person.size)

object对象

创建object{ 键值对 }

let person = {
  name: "张三",
  gender: "男",
  age: 17,
}

obj.key=value 添加属性

person.height = 175
//在对象中,每个键都是唯一的,当使用相同的键再次赋值时,会替换原来键对应的值
person.age = 25
console.log("person", person)

delete obj.key 删除属性

delete person.gender
console.log("person", person)

key in obj 检查对象是否包含指定属性

let has = "gender" in person
console.log("has", has)

获取对象的属性数量

console.log("keysArr", Object.keys(person)) //Object.keys() 用于获取对象属性名的数组
console.log("length", Object.keys(person).length)

// ['name', 'gender', 'age']
// 3

Object.entries() 对象转数组

let arr = Object.entries(person) //Object.entries() 用于获取对象的键值对数组
console.log("arr", arr)

// ['name', '张三']
// ['gender', '男']
// ['age', 17]

for(let…in…)遍历

使用for…in循环遍历对象 for…of 用于遍历可迭代对象[如数组、Set、Map、字符串等]

//for...in 用于遍历对象的可枚举属性,for in循环的 key 是下标
for (let key in person) {
  console.log("下标:",key,"值:",person[key])
}

// 下标: name 值: 张三
// 下标: gender 值: 男
// 下标: age 值: 17

forEach()遍历

Object.entries(person).forEach(([key, value]) => {
  console.log("下标:",key,"值:", value)
})

// 下标: name 值: 张三
// 下标: gender 值: 男
// 下标: age 值: 17

清空对象

person = {}
console.log("length", Object.keys(person).length)

私有属性、存取器

class Person {
   name
   #age //私有属性是指仅在类内部可访问和操作的属性, 外部无法直接访问和修改

   constructor(name, age) {
     this.name = name
     this.#age = age
   }

   //使用存取器 getter 获取私有属性
   get age() {
     return this.#age
   }

   //使用存取器 setter 设置私有属性
   set age(value) {
     this.#age= value
   }

   info() {
     return `姓名:${this.name} 年龄:${this.age}`
   }
 }
let person = new Person("张三", "17")

console.log("person", person)
// {name: '张三', #age: '17'}
console.log("age", person.age) //使用存取器 getter 获取私有属性
// age 17
console.log("info", person.info())
// info 姓名:张三 年龄:17

person.age = 25 //使用存取器 setter 设置私有属性
console.log("age", person.age)
// age 25

继承

//父类
class Person {
  name
  gender

  constructor(name, gender) {
    this.name = name
    this.gender = gender
  }

  sleep() {
  	return `${this.name} 休息中...`
  }
}

//子类
class User extends Person {
  web
  
  constructor(name, gender, hobby) {
    super(name, gender) //调用父类构造函数
    this.hobby = hobby
  }

  eat() {
  	return `${this.name} 正在吃饭...`
  }
}

let user = new User("张三", "男", "游泳")

console.log("user", user)
// {name: '张三', gender: '男', web: undefined, hobby: '游泳'}
console.log("hobby", user.hobby)
// hobby 游泳
console.log("eat", user.eat())
// eat 张三 正在吃饭...
console.log("gender", user.gender)
// gender 男
console.log("sleep", user.sleep())
// sleep 张三 休息中...

解构

可以从数组或对象中提取值并赋给变量

数组解构

let [x, y] = [1, 2]
console.log("x:", x, "y:", y)
// x: 1 y: 2

let [, , c] = [10, 20, 30]
console.log("c:", c)
// c: 30

扩展运算符

let [A, ...B] = [1, 2, 3, 4, 5, 6]
console.log("A:", A, "B:", B)
// A: 1  B:[2, 3, 4, 5, 6]

let [x2, y2 = 200] = [100] //默认值
console.log("x2:", x2, "y2:", y2)
// x2: 100 y2: 200

数据交换

let x3 = 10
let y3 = 20
let z3 = 30; //不加分号会报错
[x3, y3, z3] = [y3, z3, x3]
console.log("x3:", x3, "y3:", y3, "z3:", z3)
// x3: 20 y3: 30 z3: 10

对象解构

let person = {
  name: '张三',
  gender: '男',
  age: 17
}

let { name } = person
console.log("name:", name)
// name: 张三

重命名

let { name: userName, gender, web } = person
console.log("userName:", userName, "gender:", gender, "age:", 17)
// userName: 张三 gender: 男 age: 17

默认值

let { address = "重庆" } = person
console.log("address:", address)
// address: 重庆

Promise

Promise 表示承诺在未来的某个时刻可能会完成并返回结果

对于某些需要时间来处理结果的操作, 如用户登录、读取文件等, 可以使用 Promise 对象来执行异步操作

Promise 对象有三种状态 pending(待处理)、fulfilled(已履行)、rejected(被驳回)

  • 当创建一个 Promise 对象时, 它的初始状态为 pending, 表示异步执行还未完成
  • 异步执行成功时, 会调用 resolve 函数把 Promise 对象的状态改变为 fulfilled, 可通过 then 方法来获取异步操作的结果
  • 异步执行异常时, 会调用 reject 函数把 Promise 对象的状态更改为 rejected, 可通过 catch 方法来处理错误

pending-待处理

let promise = new Promise((resolve, reject) => {
})

//当创建一个 Promise 对象时, 它的初始状态为 pending, 表示异步执行还未完成
console.log("promise:", promise) //pending

fulfilled-已履行

let promise = new Promise((resolve, reject) => {
  resolve("邮件发送成功") //异步执行成功
})
//当异步执行成功时, 会调用 resolve 函数把 Promise 对象的状态改变为 fulfilled, 可通过 then 方法来获取异步操作的结果
console.log("promise:", promise) //fulfilled

promise.then(result => {
  console.log("result:", result)
})

rejected-被拒绝

let promise = new Promise((resolve, reject) => {
  reject("邮件发送失败") //异步执行失败
})
//当异步执行失败时, 会调用 reject 函数把 Promise 对象的状态更改为 rejected, 可通过 catch 方法来处理错误
console.log("promise:", promise) //rejected

promise.catch(error => {
  console.log("error:", error)
})

完整写法

let promise = new Promise((resolve, reject) => {
  //resolve("邮件发送成功")
  reject("邮件发送失败")
}).then(result => {
  console.log("result:", result)
}).catch(error => {
  console.log("error:", error)
}).finally(() => {
  console.log("异步执行结束")
})

Fetch

get请求

fetch('http://127.0.0.1/get')
.then(response => {          // 返回的解析后的json数据会传递给下一个 then() 方法中的回调函数作为参数,这个参数就是 data
  return response.json()     //response.json() 用于将响应数据解析为json格式的数据
}).then(data => {            //data 解析后的json数据
  console.log("get.data:", data)
}).catch(error => {
  console.log("get.error:", error.message)
}).finally(() => {
  console.log("get.finally")
})

post请求

fetch('http://127.0.0.1/post', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  },            
  body: new URLSearchParams({ // URLSearchParams 用于处理键值对类型的数据,并将其编码为url查询字符串
    name: '飞飞鱼',
    web: 'www.yyqsdjc.com',
  }),
}).then(response => {
  return response.json()
}).then(data => {
  console.log("post.data:", data)
}).catch(error => {
  console.log("post.error:", error.message)
}).finally(() => {
  console.log("post.finally")
})

post请求 - json

fetch('http://127.0.0.1/postJson', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ // JSON.stringify 用于将对象转换为json字符串
    name: '飞飞鱼',
    web: 'www.yyqsdjc.com',
  }),
}).then(response => {
  return response.json()
}).then(data => {
  console.log("postJson.data:", data)
}).catch(error => {
  console.log("postJson.error:", error.message)
}).finally(() => {
  console.log("postJson.finally")
})

Node.js的安装和配置

下载地址

nodejs.org

查看安装的版本

node -v

npm -v

查看当前镜像源

npm get registry

设置淘宝镜像源

npm config set registry https://registry.npmmirror.com/

Axios

Axios 是基于 Promise 的网络请求库, 它可以发送http请求并接收服务器返回的响应数据 Axios 返回的是一个 Promise 对象

Axios 不仅可以用于浏览器, 也可以用于 Node.js, 而 Fetch 主要用于浏览器

get请求

axios.get('http://127.0.0.1/get')
  .then(response => {
  console.log("get.data:", response.data)
}).catch(error => {
  console.log("get.error:", error)
}).finally(() => {
  console.log("get.finally")
})

post请求

let data = { //参数
  name: '飞飞鱼',
  web: 'www.yyqsdjc.com',
}

// 默认header是json格式的 不用写
axios.post('http://127.0.0.1/post', data, {
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  }
}).then(response => {
  console.log("post.data:", response.data)
}).catch(error => {
  console.log("post.error:", error)
}).finally(() => {
  console.log("post.finally")
})

post请求 postJson

// [axios 的默认请求头是 application/json]
axios.post('http://127.0.0.1/postJson', data)
  .then(response => {
  console.log("postJson.data:", response.data)
}).catch(error => {
  console.log("postJson.error:", error)
}).finally(() => {
  console.log("postJson.finally")
})

模块化开发

import、export

编写js

//index.js
let title = "飞飞鱼"
let web = "www.yyqsdjc.com"
let getWeb = () => "www.yyqsdjc.com"

export { title, web, getWeb } //将多个变量或函数分别导出

导入js

<script type="module">
    //从 index.js 文件中导入 title、web、getWeb 变量/函数
    import { title as webTitle, web, getWeb } from './index.js'
 	
    console.log(webTitle)
    console.log(web)
    console.log(getWeb())
</script>

default

编写js

//index.js
let title = "飞飞鱼"
let web = "www.yyqsdjc.com"
let getWeb = () => "www.yyqsdjc.com"

//将一个对象作为整体导出, 导出的对象包含 title、web、getWeb 三个属性
export default { title, web, getWeb } //将多个变量或函数分别导出

导入js

<script type="module">
    import obj from "./index.js"

    console.log(obj.title)
    console.log(obj.web)
    console.log(obj.getWeb())
</script>

as

编写js

let title = "飞飞鱼"
let web = "www.yyqsdjc.com"
let getWeb = () => "www.yyqsdjc.com"
export { title, web, getWeb } //将多个变量或函数分别导出

导入js

<script type="module">
    // import * as obj 用于避免命名冲突
    import * as obj from "./index.js"

    console.log(obj.title)
    console.log(obj.web)
    console.log(obj.getWeb())
</script>

VSCode扩展: Live Server —— 启动服务器

async、await 使用同步的方式编写异步代码

async

当一个函数被标记为 async 后, 该函数会返回一个 Promise 对象

await

只能在 async 函数内部使用, 加上 await 关键字后, 会在执行到这一行时暂停函数的剩余部分,

等待网络请求完成,然后继续执行并获取到请求返回的数据

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="axios/dist/axios.min.js"></script>
</head>

<body>
  <script>

    //回调地狱是指过度使用嵌套的回调函数,导致代码难以阅读和维护
    //get请求
    axios.get('http://127.0.0.1/get').then(response => {
      console.log("get.data:", response.data)
      if (response.data.data.web == "www.yyqsdjc.cn") {

        //get请求2
        return axios.get('http://127.0.0.1/article/get/id/1').then(response2 => {
          console.log("get2.data:", response2.data)
          if (response2.data.data.name == "飞飞鱼") {

            //get请求3
            return axios.get('http://127.0.0.1/article/get/search/title/入门').then(response3 => {
              console.log("get3.data:", response3.data)
            })
          }
        })
      }
    }).catch(error => {
      console.log("get.error:", error)
    }).finally(() => {
      console.log("get.finally")
    })

    //async/await 使用同步的方式编写异步代码, 避免回调地狱
    //优势 在处理多个异步操作的情况下, 可以使代码更简洁易读
    const getData = async () => {
      try {
        //get请求
        const response = await axios.get('http://127.0.0.1/get')
        console.log("async.get.data:", response.data)
        if (response.data.data.web === "www.yyqsdjc.cn") {

          //get请求2
          const response2 = await axios.get('http://127.0.0.1/article/get/id/1')
          console.log("async.get2.data:", response2.data)
          if (response2.data.data.name === "飞飞鱼") {

            //get请求3
            const response3 = await axios.get('http://127.0.0.1/article/get/search/title/入门')
            console.log("async.get3.data:", response3.data)
          }
        }

      } catch (error) {
        console.log("async.get.error:", error)
      } finally {
        console.log("async.get.finally")
      }
    }

    getData()

  </script>
</body>

</html>

学习网站

Licensed under CC BY-NC-SA 4.0