一、什么是ECMAScript?
什么是 ECMAScript?
- ECMAScript [ek - ma - script] 在中文中, ECMAScript 可以读作 "伊克玛Script"
- 官方定义: ECMAScript 是定义脚本语言的规范, 而 JavaScript 是遵循 ECMAScript 规范实现的一种编程语言
- 通俗说法: ECMAScript 好比是一本书的目录, 而 JavaScript 是这本书的具体内容
ES6 和 JavaScript 有什么区别?
-
ES6(ECMAScript 2015)是ECMAScript规范的第六个版本,而JavaScript是基于ECMAScript规范实现的编程语言,
-
ES6可以被看作是 JavaScript 的一个重要的版本更新:
- ES6引入了"块级作用域",使用let和const关键字来声明变量和常量,使变量的作用域清晰可控
- ES6引入了"箭头函数",箭头函数比传统的函数语法更简洁, 具有更少的冗余代码
- ES6引入了"类(Class) "的概念,这是一种基于原型的面向对象编程的语法糖, 使用类可以更方便地创建和管理对象
- ES6引入了"模板字符串", 使用反引号(`) 创建字符串可以方便地嵌入变量和表达式
- ES6引入了"解构赋值", 这是一种新的赋值语法,可以将数组或对象的属性直接赋值给变量
- ES6引入了"函数参数默认值"
- ES6引入了"Promise对象", 简化了异步编程, 使其更可读和可维护
- ES6引入了 Set、Map 等
- ES6引入了"模块化"(ES Module)
ES6兼容性
查看网址: compat-table.github.io/compat-tabl…
二、VSCode的安装和使用
-
下载地址: code.visualstudio.com
-
安装扩展:
- chinese :中文汉化插件
- open in browser :快速打开文件
- Live Server :模块化开发,需要使用本地服务器的时候
三、常量和变量
什么是变量?
- 变量(Variable) 是用于存储数据的名称(标识符),变量可以是任何类型,如 "数值、字符串" 等
//字符串类型 string
let name = "邓瑞"; //let 用于声明一个名为 "name" 的块级作用域变量, 并将其赋值为 "邓瑞"
console.log("姓名:", name);
console.log("姓名类型:", typeof name); //typeof 数据类型 类型是string
//数值类型 number
let balance = 100; //使用 number类型 表示整数
console.log("余额:", balance);
console.log("余额类型:", typeof balance); // 类型是number
let weight = 70.5;
console.log("体重:", weight);
console.log("体重类型:", typeof weight);
//【错误示范】 在同一个作用域下不可以声明两个相同名称的变量
//let weight = 60;
//先声明后赋值
let web;
web = "dengruicode.com";
console.log("web:", web);
【注】整数:没有小数部分的数字, 包括 负数、零、正数;
【注】ES6不区分整型和浮点型, 所有数字都使用 number类型表示
什么是常量?
- 常量(Constant) 是一个固定的值, 在程序运行中常量的值保持不变
const PI = 3.14; //const 用于声明一个名为 "PI" 的块级作用域常量, 并将其赋值为 3.14
console.log("PI", PI);
- 常量通常用来表示不会改变的值, 如数学中的 π(圆周率) PI≈3.14159265359
const声明的变量必须初始化,并且在声明后不能重新赋值
变量和常量有什么区别?
- 变量可以重新赋值
let age = 18;
age = 22; //变量可以重新赋值
console.log("age:", age);
const PI = 3.14;
console.log("PI", PI);
PI = 3.1415926; //错误示范 此处重新赋值编译器并不报错,但是一旦运行,浏览器控制台中就会报错
四、数据类型
字符串类型 string
- 字符串类型用于存储字符序列
let name = "邓瑞";
let web = "dengruicode.com";
数值类型 number
- 用于存储数字, 可以表示整数、浮点数
let balance = -100;
let weight = 60.5;
布尔类型 boolean
- 布尔类型只能取两个值,true(真) 和 false(假)
let tv = true;
对象 object
- 对象是一种复合的数据类型, 可以通过键值对的方式存储多个值,对象可以理解为包裹其他数据类型
- 键值对之间必须使用逗号分隔,否则编译报错
- 当大括号中没有定义内容的时候,就是一个空对象
//定义了一个包含姓名、年龄和体重的对象
let boy = {
name: "David",
age: 28,
weight: 70.5
}
console.log("boy", boy);
map
- map 是一种特殊的数据结构,用于存储键值对的有序集合
- 【注】 :打印出的数据类型是object
//定义了一个包含姓名、年龄和体重的map
let girl = new Map([
["name", "Luna"],
["age", 20],
["weight", 50.5]
])
console.log("girl", girl);
console.log(typeof girl); // object 在es6中,map类型没有分得很详细,任然是object
-
map与对象的比对:
- Map相对于对象提供了更灵活、有序、高效的键值对存储和操作方式,当需要在大量键值对中快速查找或删除特定键值对时, Map比对象更高效
- Map提供了一些便捷的方法来操作键值对, 如: get()、set()、delete()
- Map提供了一些便捷的迭代方法, 如: forEach()、keys()、values()、entries()
set
- Set 是一种特殊的数据结构, 用于存储无序且唯一的值的集合(不重复)
- set集合的元素是不重复的
let number = new Set([1, 2, 3, 4, 5]); //定义了一个包含5个"不重复"的整数的集合
console.log("number", number);
//let numbers = new Set([1, 2, 3, 4, 5, 5]); //错误示范
数组 array
- 数组是一种有序集合, 可以包含不同类型的元素,并且数组的长度是可变的
let str = ["a","b","c","b"]; //定义了一个包含4个字符串的数组
console.log("str", str);
let arr = ["1","3.14","a"];
console.log("arr", arr);
let arr = ["1","3.14","a",1];// 可以添加不同类型的数值
函数 function
- 函数是一段可重复执行的代码块,可以接收输入参数并返回一个值或执行某些操作
function add(a, b) {
return a + b
}
console.log("add", add(1, 2));
类 class
- 类是一种蓝图或模板,用于创建具有相同属性和方法的对象
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
info() {
console.log("姓名", this.name, "年龄", this.age)
}
}
const person = new Person("瑶瑶", 20)
person.info()
五、函数
<script>
//定义函数
function getWeb() {
return "dengruicode.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(6))
/*
匿名函数 【匿名函数没有显式的名称, 被视为一个函数表达式】
匿名函数可以在不需要额外命名的情况下进行定义和使用, 通常被用作“回调函数”, 即将函数作为参数传递给其他函数
回调函数是一种在特定事件或条件发生时被调用的函数, 回调函数通常用于异步编程中,
比如 success 是 ajax 中的一个回调函数, 用于处理请求成功的结果
*/
let sub = function (x, y) { //函数赋值给了一个变量 sub, 函数本身并没有一个具名标识符
return x - y
}
console.log("sub", sub(30, 5))
//箭头函数 【箭头函数是一种匿名函数】
let plus = (a, b) => { //省略 function 添加 =>
return a + b
}
console.log("plus", plus(5, 10))
//隐式返回 【在函数体内只有一个表达式的情况下, 可以省略花括号 {} 和 return 关键字】
let plus2 = (a, b) => a + b
console.log("plus2", plus2(10, 20))
</script>
六、数组
<script>
//定义数组
let arr = [10, 11];
console.log("arr", arr);
//向数组【末尾】添加一个或多个元素, 并返回修改后数组的长度
let arrLength = arr.push(12, 13);
console.log("arr", arr); //[10, 11, 12, 13]
console.log("arrLength", arrLength);
//向数组【开头】添加一个或多个元素, 并返回修改后数组的长度
arrLength = arr.unshift(8, 9)
console.log("arr", arr) //[8, 9, 10, 11, 12, 13]
console.log("arrLength", arrLength)
//删除数组中【第一个元素】, 并返回被删除元素
let delElement = arr.shift()
console.log("arr", arr) //[9, 10, 11, 12, 13]
console.log("delElement", delElement) //8
//删除数组【最后一个元素】, 并返回被删除元素
delElement = arr.pop()
console.log("arr", arr) //[9, 10, 11, 12]
console.log("delElement", delElement) //13
//删除元素, 并返回包含被删除元素的数组 splice(参数1:要删除元素的索引位置, 参数2:要删除的元素数量)
//let delArr = arr.splice(2, 1) // 删除第3个元素 【数组的索引是从 0 开始】
let delArr = arr.splice(2, 2) // 删除第3和第4个元素
console.log("arr", arr) //[9, 10]
console.log("delArr", delArr) //[11, 12]
//【颠倒】数组中元素的顺序
arr.reverse()
console.log("arr", arr) //[10, 9]
//数组中的元素【按照首字母顺序排序】
let arr2 = ['banana', 'apple', 'orange']
arr2.sort()
console.log("arr2", arr2) //['apple', 'banana', 'orange']
//数组中的元素【按照数字排序】
let arr3 = [5, 20, 13, 1, 4]
//arr3.sort() //默认情况下 sort() 方法使用【字符串排序】, 导致并没有按照数字大小排序
/*
比较函数 (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 后面
*/
arr3.sort((a, b) => a - b)
console.log("arr3", arr3) //[1, 4, 5, 13, 20]
//筛选符合条件的元素, 返回一个新的数组
let arr4 = [10, 11, 12, 13, 14, 15];
let newArr = arr4.filter((value, index) => {
return value > 12; // 筛选出大于12的
})
console.log("newArr", newArr); //[13, 14, 15]
//将多个数组或值【合并】为一个新数组
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...of【循环遍历数组】
let arr6 = ["邓瑞", "dengruicode.com", 100] //数组可以包含不同的数据类型
for (let item of arr6) {
console.log("for...of", item)
}
//使用forEach方法来【遍历】数组
arr6.forEach((value,index) => {
console.log("forEach", value,"index", index)
})
</script>
七、Set集合、扩展运算符
<script>
//创建Set集合
//let fruits = new Set() //创建一个空的Set集合
let fruits = new Set(['apple', 'orange', 'banana']) //创建一个包含初始值的Set集合
//向Set集合中【添加新的元素】
fruits.add('mango')
//fruits.add("orange") //若该元素已经存在, 则不会重复添加, 因为 Set 中的元素必须唯一
console.log("fruits", fruits)
//从Set集合中【删除元素】
fruits.delete('banana')
console.log("fruits", fruits)
//检查Set集合【是否包含指定元素】
console.log("fruits.has", fruits.has('banana'))
//获取Set【集合的大小】
console.log("fruits.size", fruits.size)
//使用 Array.from() 方法【将 Set集合 转换为 数组】
let arr = Array.from(fruits)
console.log("arr", arr)
//使用【扩展运算符】【将 Set集合 转换为 数组】
let arr2 = [...fruits]
console.log("arr2", arr2)
//扩展运算符是用于【展开可迭代对象】(如数组、字符串等)
//let web = 'dengruicode.com'
let web = '邓瑞编程'
let webArr = [...web] //使用扩展运算符将 字符串 转换为 数组
console.log("webArr", webArr) //['邓', '瑞', '编', '程'] // 展开字符串中的每一个字符
//使用for...of【循环遍历】 Set集合
for (let item of fruits) {
console.log("for...of", item)
}
//使用forEach方法来【遍历】 Set集合
fruits.forEach(value => {
console.log("forEach", value)
})
//【清空】 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)
</script>
八、Map 集合
<script>
//创建Map集合
//let person = new Map() //创建一个空的Map集合
let person = new Map([
["name", "邓瑞"],
["gender", "男"],
["web", "dengruicode.com"]
])
//向Map集合中【添加】新的元素
person.set('height', 175)
//在Map集合中, 每个键都是唯一的, 当使用相同的键再次调用 set() 方法时, 会替换原来键对应的值
person.set('web', "www.dengruicode.com")
console.log("person", person)
//【删除】元素
person.delete('gender')
console.log("person", person)
//检查Map集合【是否包含指定元素】
console.log("person.has", person.has('gender'))
//获取Map集合的【大小】
console.log("person.size", person.size)
//将Map集合【转换为数组】
let arr = Array.from(person)
console.log("arr", arr)
//使用扩展运算符将 Map集合【 转换为 数组】
let arr2 = [...person]
console.log("arr2", arr2)
//使用for...of循环遍历Map集合
//解构可以从数组或对象中提取值并赋给变量
//[key, value] 就是一种解构语法, 用于将 Map 集合中的键值对解构为 key 和 value 两个变量
for (let [key, value] of person) { // 【注】这里是[key, value]
console.log("for...of", key, value)
}
//使用forEach方法遍历Map集合的键值对
person.forEach((value, key) => { // 【注】这里是(value, key)
console.log("forEach", key, value)
})
//清空Map集合
person.clear()
console.log("person.size", person.size)
</script>
九、对象
<script>
let person = {
name: "邓瑞",
gender: "男",
web: "dengruicode.com",
}
//向对象中【添加】新的属性
person.height = 175
//在对象中,每个键都是唯一的,当使用相同的键再次赋值时,会替换原来键对应的值
person.web = "www.dengruicode.com"
console.log("person", person)
//【删除】属性
delete person.gender
console.log("person", person)
//检查对象【是否包含指定属性】
let has = "gender" in person
console.log("has", has)
//获取对象的【属性数量】
console.log("keysArr", Object.keys(person)) //Object.keys() 用于获取对象 【属性名的数组】
console.log("length", Object.keys(person).length)
//将【对象转换为数组】
let arr = Object.entries(person) //Object.entries() 用于获取对象的键值对数组
console.log("arr", arr)
//使用for...in循环遍历对象
//for...of 用于遍历可迭代对象[如数组、Set、Map、字符串等]
//for...in 用于遍历对象的可枚举属性
for (let key in person) {
console.log("for...in", key, person[key])
}
//使用forEach方法遍历对象的属性和值
Object.entries(person).forEach(([key, value]) => { // 【注】 这里需要使用结构的形式 [key, value]
console.log("forEach", key, value)
})
//【清空】对象
person = {}
console.log("length", Object.keys(person).length)
</script>
十、类class、模板字符串
<script>
class Person {
//若在类中没有显式声明属性, 但在构造函数或方法中引用了未声明的属性, 会自动将其视为实例属性
name //姓名
web //个人网站
//构造函数 用于初始化属性
constructor(name, web) {
this.name = name
this.web = web
}
//方法 返回个人信息
info() {
//return "姓名:" + this.name + " 个人网站:" + this.web
return `姓名:${this.name} 个人网站:${this.web}`; //模板字符串 符号使用的是1键左边的那个
}
}
//在面向对象编程中, 实例(instance) 是根据 类(class) 创建的具体对象, 使用 关键字new 可以创建一个类的实例
//创建 Person类 实例 传入 "姓名"、"个人网站" 参数
let person = new Person("邓瑞", "dengruicode.com")
console.log("person", person)
console.log("web", person.web)
console.log("info", person.info())
</script>
十一、私有属性、存取器
<script>
class Person {
name
#web //私有属性是指仅在类内部可访问和操作的属性, 外部无法直接访问和修改
constructor(name, web) {
this.name = name
this.#web = web; // 固定格式写法,不用纠结
}
//使用存取器 getter 获取私有属性
get web() {
return this.#web;
}
//使用存取器 setter 设置私有属性
set web(value) {
this.#web = value
}
info() {
return `姓名:${this.name} 个人网站:${this.web}`
}
}
let person = new Person("邓瑞", "dengruicode.com")
console.log("person", person)
console.log("web", person.web) //使用存取器 getter 获取私有属性
console.log("info", person.info())
person.web = "www.dengruicode.com" //使用存取器 setter 设置私有属性
console.log("web", person.web)
</script>
十二、继承extends
<script>
//父类
class Person {
name
gender
constructor(name, gender) {
this.name = name
this.gender = gender
}
sleep() {
return `${this.name} 休息中...`
}
}
//子类:可以调用父类的属性和方法
class David extends Person {
web
constructor(name, gender, web) {
super(name, gender); //调用父类构造函数
this.web = web;
}
eat() {
return `${this.name} 正在吃饭...`
}
}
let david = new David("邓瑞", "男", "dengruicode.com")
console.log("david", david)
console.log("web", david.web)
console.log("eat", david.eat())
console.log("gender", david.gender)
console.log("sleep", david.sleep())
</script>
十三、解构
<script>
//解构 可以从数组或对象中【提取值并赋给变量】
//--- 数组解构
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:", A, "B:", B); // 1 赋值给A, 2,3,4,5,6赋值给B
let [x2, y2 = 200] = [100] //默认值
console.log("x2:", x2, "y2:", y2)
//两数交换
let x3 = 10
let y3 = 20; //【注】不加分号会报错
[x3, y3] = [y3, x3]
console.log("x3:", x3, "y3:", y3)
//--- 对象解构
let person = {
name: '邓瑞',
gender: '男',
web: 'dengruicode.com'
}
let { name } = person
console.log("name:", name)
//重命名
let { name: userName, gender, web } = person
console.log("userName:", userName, "gender:", gender, "web:", web)
//默认值
let { address = "安徽" } = person
console.log("address:", address)
</script>
十四、字符串
<script>
let web = "dengruicode.com"
// 字符串长度
let len = web.length
console.log("字符串长度:", len)
// 转小写
let str1 = "DAVID".toLowerCase()
console.log("转小写:", str1)
// 转大写
let str2 = "luna".toUpperCase()
console.log("转大写:", str2)
// 返回字符串在索引处的字符
let str3 = web[2]
console.log("返回字符串在索引处的字符:", str3)
// 字符串转为字符数组
let str4 = [...web]
console.log("字符串转为字符数组:", str4)
// 字符串转 int
let number = parseInt("168")
console.log("字符串转int:", number)
// 字符串替换
let str6 = web.replaceAll("co", "y")
console.log("替换全部字符串:", str6)
let str7 = web.replace("co", "y")
console.log("替换1个字符串:", str7)
// 去除字符串两侧指定的字符
let str8 = " dengruicode.com ".trim()
console.log("去除字符串两侧指定的字符:", str8)
// 判断是否包含某个字符串
let result = web.includes("dengrui") // true
console.log("是否包含某个字符串:", result)
// 返回字符串中第一次出现某个字符串的位置,若不存在则返回-1
let result2 = web.indexOf("dengrui")
console.log("返回字符串中第一次出现某个字符串的位置:", result2)
let result3 = "www.dengruicode.com".indexOf("dengrui")
console.log("返回字符串中第一次出现某个字符串的位置:", result3)
// 判断一个字符串是否以指定的前缀开头
let result4 = "www.dengruicode.com".startsWith("www")
console.log("判断一个字符串是否以指定的前缀开头:", result4)
// 判断一个字符串是否以指定的后缀结尾
let result5 = "www.dengruicode.com".endsWith("net")
console.log("判断一个字符串是否以指定的后缀结尾:", result5)
// 将字符串按照指定字符分割成数组
let arr = "a,b,c,d".split(",")
console.log("将字符串按照指定字符分割成数组:", arr)
// 字符串截取 substr(开始位置,截取长度)
let subStr = web.substr(0, 7) //dengrui
console.log("截取字符串的前7个字符:", subStr)
let subStr2 = web.substr(-3) //com
console.log("截取字符串的最后3个字符:", subStr2)
let subStr3 = web.substr(4) //ruicode.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(10, "-")
console.log("padEnd:", padEnd)
</script>
十五、Promise
/*
Promise 表示承诺在未来的某个时刻可能会完成并返回结果
对于某些需要时间来处理结果的操作, 如用户登录、读取文件等, 可以使用 Promise 对象来执行异步操作
Promise 对象有三种状态:
pending(待处理)
fulfilled(已履行)
rejected(被驳回)
当创建一个 Promise 对象时, 它的初始状态为 pending, 表示异步执行还未完成
当异步执行成功时, 会调用 resolve 函数把 Promise 对象的状态改变为 fulfilled, 可通过 then 方法来获取异步操作的结果
当异步执行异常时, 会调用 reject 函数把 Promise 对象的状态更改为 rejected, 可通过 catch 方法来处理错误
注:异步操作是指在程序执行过程中, 某个操作不会立即返回结果, 而是需要一段时间的等待
let promise = new Promise((resolve, reject) => {
})
//当创建一个 Promise 对象时, 它的初始状态为 pending, 表示异步执行还未完成
console.log("promise:", promise) //pending
let promise = new Promise((resolve, reject) => {
resolve("邮件发送成功") //异步执行成功
})
//当异步执行成功时, 会调用 resolve 函数把 Promise 对象的状态改变为 fulfilled, 可通过 then 方法来获取异步操作的结果
console.log("promise:", promise) //fulfilled
promise.then(result => {
console.log("result:", result)
})
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 驳回
//resolve("邮件发送成功")
reject("邮件发送失败")
}).then(result => {
console.log("result:", result)
}).catch(error => {
console.log("error:", error)
}).finally(() => {
console.log("异步执行结束")
})
十六、Fetch
/*
fetch 是基于 Promise 的 api(网络请求库), 它可以发送http请求并接收服务器返回的响应数据
fetch 返回的是一个 Promise 对象
*/
//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请求 post
fetch('http://127.0.0.1/post', {
method: 'POST',
headers: { // headers这个参数,在前后端调试的时候可以使用下,如果后端接收不到数据,就加上这个参数
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({//URLSearchParams 用于处理键值对类型的数据,并将其编码为url查询字符串
name: '邓瑞',
web: 'dengruicode.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请求 postJson
fetch('http://127.0.0.1/postJson', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({//JSON.stringify 用于将对象转换为json字符串
name: '邓瑞编程',
web: 'www.dengruicode.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/zh-cn
-
查看安装的版本:
node -v #node的版本 npm -v #npm的版本 -
查看当前镜像源
npm get registry
-
设置淘宝镜像源
npm config set registry registry.npmmirror.com/
-
【注】
-
Node.js是一个开源的JavaScript运行时环境, 用于在服务器端运行JavaScript代码
-
npm(Node Package Manager)是Node.js包管理器, 用来安装各种库、框架和工具
- 比如: npm install axios
- axios 使用 unpkg CDN:
-
十八、Axios
/*
Axios 是基于 Promise 的网络请求库, 它可以发送http请求并接收服务器返回的响应数据
Axios 返回的是一个 Promise 对象
Axios 不仅可以用于浏览器, 也可以用于 Node.js, 而 Fetch 主要用于浏览器
*/
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
//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请求 post
let data = { //参数
name: '邓瑞',
web: 'dengruicode.com',
}
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")
})
十九、模块化开发
模块化开发:是指将复杂的代码拆分为独立的模块,每个模块负责完成特定的功能,
不同的模块之间可以通过使用export关键字将代码【导出】为模块,其他模块可以使用import关键字【导入】该模块
------ import、export
//index.js
let title = "邓瑞编程"
let web = "dengruicode.com"
/*
let getWeb = () => {
return "www.dengruicode.com"
}
*/
let getWeb = () => "www.dengruicode.com"
export { title, web, getWeb } //将多个变量或函数分别导出
<script type="module">
//从 index.js 文件中导入 title、web、getWeb 变量/函数
import { title as webTitle, web, getWeb } from './index.js' // as 定义别名
console.log(webTitle)
console.log(web)
console.log(getWeb())
</script>
------ default
//index.js
let title = "邓瑞编程"
let web = "dengruicode.com"
let getWeb = () => "www.dengruicode.com"
//将一个对象作为整体导出, 导出的对象包含 title、web、getWeb 三个属性
export default { title, web, getWeb }
<script type="module">
import obj from "./index.js"
console.log(obj.title)
console.log(obj.web)
console.log(obj.getWeb())
</script>
------ as
//index.js
let title = "邓瑞编程"
let web = "dengruicode.com"
let getWeb = () => "www.dengruicode.com"
export { title, web, getWeb } //将多个变量或函数分别导出
<script type="module">
import * as obj from "./index.js" // * 表示导出的所有的对象
console.log(obj.title)
console.log(obj.web)
console.log(obj.getWeb())
</script>
- 注: import * as obj 用于避免命名冲突
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 == "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/await 【使用同步的方式编写异步代码, 避免回调地狱(回调地狱:过度使用回调函数,导致代码难以阅读和维护)】
//【优势】 在处理多个异步操作的情况下, 可以使代码更简洁易读
const getData = async () => { // 会返回一个 Promise 对象
try {
//get请求
const response = await axios.get('http://127.0.0.1/get') // 加上 await 关键字后, 会在执行到这一行时暂停函数的剩余部分
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()
</script>
</body>
</html>