ECMAScript是什么

简单来说就是JavaScript具有划时代意义的一个版本(2015 年 6 月正式发布),具体为什么叫ECMAScript,可以看阮一峰的《ECMAScript6入门》

本文的写作目的其实是回忆起一些常用的ES6变量、方法,作为一个个人的学习记录。本机使用的是Node.js v18.15.0

关于版本的兼容性问题可以看: https://compat-table.github.io/compat-table/es6

变量与常量 let const

早期学习过js或者看了老资料的都看过一个关键字——var,这个关键字存在变量提升的问题,这时候就容易出现指针混乱。

在ES6中使用更加规范的constlet作为var关键字的替代,将声明的变量都限制在代码块中且不允许变量的提升。

  • let 变量 可后期修改,只服务于当前的块级作用域{ }
  • const 常量 不可后期修改,在声明后即可使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 变量 经常改变的数据类型
let name = "gcnanmu";
console.log(name)
console.log(typeof name)

let balance = 100;
console.log(balance)
console.log(typeof balance)

// 常量
const pi = 3.14
console.log("PI",pi)

// 常量与变量的区别
name = "gcnanmu2"
console.log(name)

// 报错
pi=3
console.log(pi)

提一嘴,在ES6之后都不用在代码的末尾添加;

数据类型 typeof

我们日常说ES6基本指的是2015年之后的所有版本,所以网上对ES6有几种数据类型说法很多,但是常用的就那么几个数据类型,分别是数组(array),数字(number)、字符串(string)、对象(object)、集合(set)、布尔(boolen),函数(function),类(class),map等八种类型。

想要查看当前的数据类型,有三种常用的方法:

  1. typeof 变量
  2. Object.prototype.toString.call(变量)
  3. 变量.constructor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// string
let name = "gcnanmu";

// number
// js没有浮点数类型的说法
let balance = -100;
let weight = 60.5;

// boolen true/false
let tv1 = true;
let tv2 = false;
console.log("tv1", tv1, typeof tv1)
console.log("tv2", tv2, typeof tv2)

// object
// 可以包裹其他数据类型,是一个集合体
// 有多个键值对组成 每个键值对之间要使用逗号分隔
let boy = {
name: "gcnanmu",
age: 20,
weight: 60.5
}
console.log("boy", boy, typeof boy)

// map集合
// 用于储存键值对的数据类型
// 使用箭头进行指向 打印出的类型还是object
let girl = new Map([
["name", "luna"],
["age", 18]
])
console.log("girl", girl, typeof girl)

// set
// 元素是不能重复的
let number = new Set([1, 2, 3, 2, "2"])
console.log("number", number, typeof number)

// array
// 可以添加重复的数据
let arr = ["a", "b", "c", "b", "c"]
console.log("arr", arr, typeof arr)

// function
function myFunction(a, b) {
console.log(a, b)
return a + b
}

let result = myFunction(1, 2)
console.log("result", result)


// class
// 创建相同属性的和方法的对象
class Person {
// constructor是构造方法
constructor(name, age) {
this.name = name
this.age = age
}

info() {
console.log("name", this.name, "age", this.age)
}
}

let my = new Person("gcnanmu", 23)
my.info()

其中数据类型又可以继续划分为两种:

  • 基本数据类型:number,string,boolen等
  • 引用数据类型:object,map,function等

对于这两种数据类型,需要注意的就是引用数据类型的赋值操作赋值的是地址,而不是数据本身。

函数 function

函数很像数学的概念,输入一个x,根据编写的逻辑处理得到一个新的值。在ES6中为了方便函数的书写(偷懒),引入了箭头函数和隐士返回两个新特性。

箭头函数是为了方便匿名函数书写的,有了箭头函数后,可以将匿名函数省略大半:

1
2
3
4
5
6
7
8
9
// 普通的写法
let sub = function (x, y) {
return x - y
}

// 箭头函数
let plus = (a, b) => {
return a + b;
}

如果你只有一个返回值,那么还可以进一步将return省略(即隐士返回):

1
2
3
4
5
6
7
// 省略前
let plus = (a, b) => {
return a + b;
}

// 省略后
let plus = (a , b) => (a+b)

数组 Array

数组可能是我们编写函数最常用的数据类型。因为使用的评率太高,所以方法都必须要牢记。基本操作分为增删改查和排序。常用的属性为length。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
let arr = [10, 11];
console.log("arr", arr)

// push 向末尾添加一个或多个元素,返回数组的长度
let arrlength = arr.push(12, 13)
console.log("arr", arr)
console.log("arrlength", arrlength)

// unshift 向开头添加元素,返回数组的长度
arrlength = arr.unshift(8, 9);
console.log("arr", arr)
console.log("arrlength", arrlength)

// shift 删除第一个元素,返回删除的元素
let delElement = arr.shift()
console.log("delElement", delElement)

// pop 删除末尾的一个元素 返回被删除的元素
delElement = arr.pop()
console.log("delElement", delElement)

// splice 删除指定的元素 返回被删除元素的数组
let delArr = arr.splice(2, 2)
console.log("arr", delArr)

// reverse 颠倒元素 无返回值
arr.reverse()
console.log("arr", arr)

// sort 按照首字母排列
// 注意对数组进行排序的时候也是按照首字母来排序的
let arr2 = ["banana", "apple", "orange"]
arr2.sort()
console.log("arr2", arr2)

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

// 筛选符合条件的数组 返回一个新的数组
let arr4 = [10, 11, 12, 13, 14, 15]
let newArr = arr4.filter((value) => {
return value > 12
})
console.log("newArr", newArr)

// for循环
for (let item of arr2) {
console.log(item)
}

// each方法
arr2.forEach((value, index) => {
console.log(index, value)
})

// 数组切片
console.log(arr2.slice(0, 1)); //apple
console.log(arr2.slice(0, 2)); //apple banana

这边要提一嘴两个不同的for循环:

  • for of 取出的是其中的元素

    1
    2
    3
    for (let num of number) {
    console.log(num);
    }
  • for in 按顺序遍历下标,而不是元素

    1
    2
    3
    4
    5
    6
    7
    for (let num in number) {
    console.log(number[num]);
    }
    // 等价
    for (let i = 0; i < number.length; i++) {
    console.log(number[i]);
    }

在很多公司的面试题中还出现了reduce方法,这个方法常见的用法是累计的计算:

1
2
3
4
5
6
7
8
let number = [1, 1, 2, 3];

let result = number.reduce((pre, cur) => {
console.log(pre, cur);
return pre + cur;
});

console.log(result);

输出为:

1
2
3
4
1 1
2 2
4 3
7

另外,个人感觉js的循环也挺反直觉的,一般的语言都是(index,key,value)组合,而js是(value,key,index)

集合 Set

集合和数学上的集合一样,常用来存储简单的数据类型,里面不存在重复的元素,常见的用法是用来去重。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
let fruits = new Set(["apple", "banana", "orange"])
console.log(fruits)

// add
fruits.add("mango")
console.log(fruits)

// delete
fruits.delete("banana")
console.log(fruits)

// has 是否在集合之内
console.log(fruits.has("apple"));
console.log(fruits.has("banana"));

// size
console.log(fruits.size)

// change to array
console.log(typeof fruits)
let arr = Array.from(fruits)
console.log(typeof arr)

// 扩展运算符 展开可迭代对象
let web = "gcnanmu3125.xyz"
let web2 = "工程楠木"
let webArr = [...web]
let webArr2 = [...web2]
console.log(webArr)
console.log(webArr2)

// 可使用扩展运算符将set转化为数组
console.log([...fruits])

// for
for (let item of fruits) {
console.log(item)
}


// set集合没有索引 索引还是他自身
fruits.forEach((value, index) => {
console.log(index, value)
})

// 将数组去重
let numberArr = [1, 2, 3, 3, 2, 1]
let numberSet = new Set(numberArr)
console.log(
numberSet
)

这边有提到一个打散的语法,可以将string这种对象直接打散为列表形式:

1
2
3
4
5
6
7
8
9
10
let name = "gcnanmu"

console.log([...name]);
/*
[
'g', 'c', 'n',
'a', 'n', 'm',
'u'
]
*/

字符串 String

字符串和array的使用频率差不了太多,因此也需要单独记忆。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
let web = "www.BaiDu.com"

// length
console.log(web.length)

// 转小写
console.log(web.toLowerCase())

// 转大写
console.log(web.toUpperCase())

// 取特定位置的字符
console.log(web[2])


// 打散转化为数组
let strArr = [...web]
console.log(strArr)

// 转化为int
let number = parseInt("168")
console.log(number)

// 字符串替代
let str1 = web.replaceAll("co", "y")
console.log("替换全部", str1)

let str2 = web.replace("co", "y")
console.log("替换第一个出现", str2)

// 去掉两侧指定字符
let str3 = " baidu.com ".trim()
console.log(str3)

// 是否包含某个字符串
let result = web.includes("Baidu") // true
console.log("是否包含某个字符串:", result)

// 返回字符串中第一次出现某个字符串的位置,若不存在则返回-1
let result2 = web.indexOf("Baidu")
console.log("返回字符串中第一次出现某个字符串的位置:", result2)

// 判断一个字符串是否以指定的前缀开头
let result4 = "www.baidu.com".startsWith("www")
console.log("判断一个字符串是否以指定的前缀开头:", result4)

// 判断一个字符串是否以指定的后缀结尾
let result5 = "www.baidu.com".endsWith("net")
console.log("判断一个字符串是否以指定的后缀结尾:", result5)

// 将字符串分割为数组
let arr = "a,b,c,d".split(",")
console.log("将字符串按照指定字符分割成数组:", arr)

// 字符串截取 substr(开始位置,截取长度)
let subStr = web.substring(0, 7) //dengrui
console.log("截取字符串的前7个字符:", subStr)

// subString不接收负数
let subStr2 = web.substring(web.length - 3) //com
console.log("截取字符串的最后3个字符:", subStr2)

let subStr3 = web.substring(4) //baidu.com [字符串下标是从 0 开始]
console.log("从字符串的第5个位置开始截取直至字符串末尾:", subStr3)

//重复字符串
let repeatstr = "David".repeat(3)
console.log("重复3次字符串", repeatstr)


//在字符串前添加指定数量的填充字符, 直到该字符串达到指定的长度
let padStart = "David".padStart(15, "-") //由于 David 占 5 个字符, 因此只需要再添加 10 个横线, 即可达到总长度 15
//let padStart = "David".padStart(15) //默认空格
console.log("padStart:", padStart)

//在字符串后添加指定数量的填充字符, 直到该字符串达到指定的长度
let padEnd = "David".padEnd(15, "-")
console.log("padEnd:", padEnd)

集合 Map

Map集合存储键值对的数组,使用键值对来存储信息。下面是一个例子:

1
2
3
4
5
6
7
8
9
10
let website = new Map([
["百度", "https://www.baidu.com"],
["谷歌", "https://www.google.com"],
["bing", "https://www.bing.com"],
]);

// 返回的都是可迭代对象
console.log(website.keys());
console.log(website.values());
console.log(website.entries());

打印的输出为:

1
2
3
4
5
6
7
8
9
10
11
[Map Iterator] { '百度', '谷歌', 'bing' }
[Map Iterator] {
'https://www.baidu.com',
'https://www.google.com',
'https://www.bing.com'
}
[Map Entries] {
[ '百度', 'https://www.baidu.com' ],
[ '谷歌', 'https://www.google.com' ],
[ 'bing', 'https://www.bing.com' ]
}

一些常见的操作如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// 存储键值对的数组

let teacher = new Map([
["name", "gcnanmu"],
["gender", "man"],
["web", "baidu.com"]
])
console.log(teacher)

// add
teacher.set("height", 175)
console.log(teacher)

// delete
teacher.delete("gender")
console.log(teacher)

// has
console.log(teacher.has("gender"))
console.log(teacher.has("web"))

// edit
// 每个键都是唯一的
teacher.set("web", "www.baidu.com")
console.log(teacher)

// size
console.log(teacher.size)


// change to array
let arr = Array.from(teacher)
console.log(arr)

let arr2 = [...teacher]
console.log(arr2)

// for 将键值对转化为数组并打印
for (let item of teacher) {
console.log(item)
}

// 解构
// 有键值对可以进行解构
for (let [key, value] of teacher) {
console.log(key, value)
}

// each 记住index是写在后面的
teacher.forEach((value, key) => {
console.log(key, value)
})

// clear
teacher.clear()
console.log(teacher)

对象 object

这个对象挺像Python中的dict,更像Python的数据类(@dataclass),使用.来获取属性值,它是不可迭代的,写法也很简单。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
let teacher = {
name: "gcnanmu",
gender: "man",
web: "baidu.com"
}

console.log(teacher)

// add
teacher.height = 175
console.log(teacher)

// edit
teacher.web = "www.baidu.com"
console.log(teacher)

// delete
delete teacher.gender
console.log(teacher)

// container
let has = "gender" in teacher
console.log(has)

let has2 = "name" in teacher
console.log(has2)

// 打印对象的属性名
console.log(Object.keys(teacher));
console.log(Object.keys(teacher).length);

// 遍历
// 不可以使用of进行 因为不可迭代
for (let key in teacher) {
console.log("for……in key", key, teacher[key])
}

// 转化为键值对数组
console.log(Object.entries(teacher));

Object.entries(teacher).forEach(([key, value]) => {
console.log("foreach ",key, value)
})

// clear
teacher = {}
console.log(teacher)

类和私有属性 class

类是面向对象的起始方法,用于将具有相同属性或相同方法的数据结构放在一起,一般来说构造方法(constructor)内都是可访问的数据,也可以使用语法将其私有化。

方法有两种:

  1. 变量名前加#,此方法前面不能加this
  2. 变量前加_
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Person {
#web = "www.baidu.com";
constructor(name, age) {
this.name = name;
// 将age设为私有变量
this._age = age;
}

sayHello() {
console.log(
`Hello, my name is ${this.name}, I am ${this.age} years old.`
);
}

// 加上后私有变量就会失效
get web() {
return this.#web;
}

set web(value){
this.#web = value;
}

// 使外界能够访问私有变量
get age() {
return this._age;
}

set age(value) {
this._age = value;
}
}

语法和Python十分相似,甚至私有化也非常相似。

类的继承 extends

在数学中,集合与集合之间肯定存在交集的情况,类与类也是类似,比如我属于Person类,我有人一些共有的属性,比如我要吃饭和睡觉,这时候就不需要再重写编写相应的函数,只需要从父类中继承即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Person {
name
gender

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

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

// 继承
class Me extends Person {
web

constructor(name, gender, web) {
super(name, gender);
this.web = web
}

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

sleep() {
return `${this.name}在睡觉……`
}

}

let person = new Me("wo", "男", "baidu.com")

console.log(person.name)
console.log(person.eat())
console.log(person.sleep())

打印的结果是:

1
2
3
wo
wo在吃饭……
wo在睡觉……

解构 {属性名}

解构的作用是将对象中的部分元素或者数组通过命名提取的方法来取出个别元素(可非连续)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 定义一个数组并赋值给x,y
let [x, y] = [1, 2]
console.log(`x:${x} y:${y}`)

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

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

let [x2, y2 = 200] = [100]
console.log(x2, y2)

// 两数交换
let x3 = 10
let y3 = 20;// 不加分号会报错
[x3, y3] = [y3, x3]
console.log(x3, y3)

// 对象结构
let person = {
name: "gcnanmu",
gender: "man",
web: "baidu.com"
}

let {name} = person
console.log(name)

// 使用了对象重命名
let {name: userName, gender, web} = person
console.log(userName, gender, web)

promise

promise是异步编程操作函数,和Python的try用法相同。promise是通过fulfilled和reject来判断是否成功运行,当然也可以直接不写,交给函数来判断。

  • fulfill - 走then(resolve)
  • reject - 走catch(reject)
  • pending - 正在处理中
  • finally - 无论是fulfill还是reject都会执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 可以直接拼接在一起
let promise = new Promise((resolve, reject) => {
// fulfilled-执行成功 可以进一步执行then函数
// resolve("还钱了")
// reject - 执行错误 可以进一步进入catch函数
reject("没有还钱")
}).then(result => {
// 返回的结果就是resolve中的结果
console.log(result)
}).catch(error => {
console.log(error)
}).finally(() => {
console.log("异步执行结束")
})

// 不写
promise.then(result => {
console.log(result)
}).catch(error => {
console.log(error)
}).finally(() => {
console.log("异步执行结束")
})

fetch

fetch 是用于异步网络请求的函数,可以用来获取或发送数据,接收后会返回promise对象。常见的请求方式有get和post两种,因为网络中一般都发送json格式的数据,接收后还需要转化一下格式。

这里需要展示一下API请求工具,来自邓瑞。

访问http://127.0.0.1/get可看到数据的格式:

1
2
3
4
5
6
7
8
9
{
"data": {
"gender": "男",
"name": "邓瑞",
"web": "dengruicode.com"
},
"msg": "get请求",
"status": "success"
}

data为具体的数据,msg为请求的描述,status用来展示请求是否有效

  • 获取接收get请求

    1
    2
    3
    4
    5
    6
    7
    8
    9
    fetch("http://localhost/get").then(response => {
    return response.json()
    }).then(data => {
    console.log("get-data", data)
    }).catch(error => {
    console.log("get-error", error)
    }).finally(() => {
    console.log("get-finally")
    })
  • 发送post请求

    post请求一般是键值对的形式,可以使用URLSearchParams来获得键值对数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    fetch('http://localhost/post', {
    // 显示定义
    method: 'POST',
    headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
    },
    //URLSearchParams 用于处理键值对类型的数据,并将其编码为url查询字符串
    body: new URLSearchParams({
    name: '百度',
    web: 'baidu.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")
    })

    如果想要直接获得Json数据,可以使用JSON.stringify对象,且在于请求头请求类型不同

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // json参数
    //post请求 postJson
    fetch('http://127.0.0.1/postJson', {
    method: 'POST',
    headers: {
    'Content-Type': 'application/json',
    },
    body: JSON.stringify({//JSON.stringify 用于将对象转换为json字符串
    name: '百度',
    web: 'www.baidu.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

Node.js其实是JavaScript的一个解释器,npm则是Node Package Manager的缩写,就是一个Node.js的一个管理包的工具,网站为npmjs.com,可以从上面下载包,也可以使用命令进行下载。

下载Node.js,LTS是稳定版,Current是最新发行版。

Node.js — Download Node.js® (nodejs.org)

下载后使用下面的命令查看node.js版本和npm版本

1
node -v
1
npm -v

查看当前npm的镜像源:

1
npm get registry

默认输出是 https://registry.npmjs.org

和Python一样,如果想要访问默认的镜像源下载,很容易出现超时的问题,这里推荐更换镜像源。

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

这里更换的是淘宝的镜像源。

Axios

axios是基于promise的请求库,他可以发送http请求并接受服务器返回相应的数据,返回的是一个Promise对象 既可以应用于浏览器,也可用于[Node.js](Node.js — Run JavaScript Everywhere (nodejs.org))。

可以通过npm命令进行下载:

1
npm install axios

可能发现下载了很多模块,只需要导入名为axios.min.js文件即可。

1
<script src="../js/axios.js"></script>

也可以直接使用cdn

1
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  • 获取get

    1
    2
    3
    4
    5
    6
    7
    8
    axios.get('http://127.0.0.1/get').then(response => {
    // 不需要再返回json格式 默认就是json格式
    console.log("get.data:", response.data)
    }).catch(error => {
    console.log("get.error:", error)
    }).finally(() => {
    console.log("get.finally")
    })
  • 获取post请求

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //post请求 post
    let data = { //参数
    name: '百度',
    web: 'baidu.com',
    }

    // 不需要再将数据转化为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")
    })

    因为axios 的默认请求头是 application/json,因此可以不用指定headers

    1
    2
    3
    4
    5
    6
    7
    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")
    })

模块化开发 export import

模块化开发的本质就是将需要使用的数据或方法使用export导出,后续就可以在其他js中使用import导入export导出的数据或者方法

先创建一个index.js文件

1
2
3
4
5
6
7
8
9
let title = "百度"
let web = "baidu.com"


let getWeb = () => {
return `title: ${title}, web: ${web}`
}

export {title,web,getWeb}

后续便可以在html模版中导入(Node.js不支持在模版之外的其他地方使用import)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script type="module">
import {title as webTitle, web, getWeb} from "./index.js"

console.log(webTitle)
console.log(web)
console.log(getWeb())

</script>
</body>
</html>

如果想要将导入的数据作为一个对象整体使用可以在导入时候作为一个obj:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script type="module">
import * as obj from "./index.js"

console.log(obj.title)
console.log(obj.web)
console.log(obj.getWeb())

</script>
</body>
</html>

也可以修改index.js

1
2
3
4
5
6
7
8
9
let title = "百度"
let web = "baidu.com"


let getWeb = () => {
return `title: ${title}, web: ${web}`
}

export default {title,web,getWeb}

后续就可以直接导入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script type="module">
import obj from "./index.js"

console.log(obj.title)
console.log(obj.web)
console.log(obj.getWeb())

</script>
</body>
</html>

异步 async

async关键字一般要配合await关键字使用,用来完成异步请求操作。使用异步的好处是不会因为等待耗时的操作而影响主线程的执行(主线程阻塞)。可以使用同步的方式编写异步代码。

  1. 当一个函数被标记为async后,该函数会返回一个Promise对象
  2. await只能在async内部使用,加上await关键字后,会执行到这一行暂停函数的部分
  3. 等到网络请求完成,然后继续执行并获取到请求返回的数据

非异步操作的话是这样写的:

1
2
3
4
5
6
7
axios.get("https://localhost/get").then(response => {
console.log("get_data", response.data)
}).catch(error => {
console.log("get_error", error)
}).finally(() => {
console.log("get.finally")
})

如果使用异步关键字,可改为如下形式:

1
2
3
4
5
6
7
8
9
10
11
const getData = async () => {
try {
const response = await axios.get("https://localhost/get")
console.log("async.get.data", response.data)
} catch (error) {
console.log("async.get_error", error)
} finally {
console.log("async.get.finally")
}
}
getData()

还有一个作用是避免回调地狱,。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
axios.get('http://127.0.0.1/get').then(response => {
console.log("get.data:", response.data)
if (response.data.data.web == "dengruicode.com") {

//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和wait后会变成如下,简洁了不少:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//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 === "dengruicode.com") {

//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()