了解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>