ES6
1. let
let用来变量声明
特性:1.变量不能重复声明 2.块级作用域 3.不会变量提升
2. const
const用来声明常量
特性:1.一定要有初始值 2.值不能修改 3.块级作用域 4.对于数组或者对象的修改不算对常量的修改,不会报错
3. 变量的结构赋值
-
ES6允许按照一定模式从数组和对象中提取值,对变量进行复制
-
数组的结构
const XXX = ['xx','yy','zz'] let [x,y,z] = XXX
-
对象的结构
const zhao = { name:'xxx', age:18, say: function(){} } let {say} = zhao
-
4. 模板字符串
新的字符串方式,用``声明
特性:1.内容中可以直接出现换行符 2.用${}直接进行变量拼接
5. 对象的简化写法
ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法
6. 箭头函数
ES6允许使用箭头来定义函数
特性:1.this是静态的,始终指向函数声明式所在的作用域下的this值 2.不能作为构造函数实例化对象 3.不能使用arguments变量
适用场景:与this无关的回调,定时器,数组的方法回调
不适用场景:与this有关的回调,事件回调,对象的方法
7. 函数参数的默认值
ES6允许参数赋初始值
// 如果不给c赋值,那么c就会等于初始值10
function add (a,b,c=10){}
8.rest参数
ES6引入rest参数,用于获取函数的实参,用来代替argument
function date(...args){
console.log(args) // args是一个装剩余参数的数组,可以使用数组方法
}
9.扩展运算符
... 扩展运算符能将数组转换为逗号分隔的参数序列
const xxx = [1,2,3]
console.log(...xxx) // 1,2,3
const xxx = {
name: 'xxx',
age: 18
}
console.log(...xxx) // name:'xxx', age:18
与rest参数的区别:rest参数是形参,只能放在函数声明的参数里,扩展运算符可以展开数组,对象,伪数组
使用扩展运算符展开的元素是浅拷贝
10.Symbol
ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值,他是JavaScript语言的第七种数据类型
特点:1. Symbol的值是唯一的,用来解决命名冲突的问题 2.Symbol值不能与其他数据进行运算 3.Symbol定义的对象属性不能使用for in 循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名
11.迭代器(Iterator)
迭代器是一种接口,为各种不同的数据结构提供了统一的访问机制,任何数据结构只要部署了Iterator接口,就可以完成遍历操作
-
ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费
-
for of保存的是键值,for in 保存的是键名
-
-
原生具备iterator接口的数据(可用for of遍历)
-
Array 2.Arguments 3.Set 4.Map 5.String 6.TypeArray 7.NodeList
-
-
工作原理
-
创建一个指针对象,指向当前数据结构的起始位置
-
第一次调用对象的next方法,指针自动指向数据结构的第一个成员
-
接下来不断调用next方法,调用一直往后移动,直到指向最后一个成员
-
每调用next方法返回一个包含value和done属性的对象
-
-
场景:自定义遍历数据
let obj = { name:'xxx', stus:['xxx','yyy','zzz','aaa'], // 开启一个迭代器,来自定义遍历数据 [Symbol.iterator](){ let index = 0; return { next:() => { if(index < this.stus.length){ const res = {value: this.stus[index], done:false} index++ return result }else { return {value:undefined, done:true} } } } } }
12.生成器
生成器是ES6提供的一种异步编程方式,语法行为与传统的函数完全不同
function * gen(){ // 生成器是一个特殊的函数
console.log(111)
yield 'xxxx' // yield算是函数代码的分隔符,每掉一次next就会执行到一个yield的位置
console.log(222)
yield 'xxxx'
console.log(333)
yield 'xxxx'
console.log(444)
}
解决异步编程
function getUsers() {
setTimeout(() => {
let data = '用户数据'
iterator.next(data)
}, 1000}
}
function getGoods() {
setTimeout(() => {
let data = '商品数据'
iterator.next(data)
}, 1000}
}
function getOrders() {
setTimeout(() => {
let data = '订单数据'
iterator.next(data)
}, 1000}
}
function * gen(){
let users = yield getUsers();
console.log(users)
let orders = yield getOrders();
console.log(orders)
let goods = yield getGoods();
console.log(goods)
}
let iterator = gen()
iterator.next()
13.Promise
Promise 是ES6引入的异步编程的新解决方法,语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果
callback hell:
// 通过回调的方式来保证异步函数的执行顺序,但会陷入回调地狱
fs.readFile('/data/a.txt', 'utf8', (err, data) => {
if(err) {
throw err
}
console.log(data)
fs.readFile('/data/b.txt', 'utf8', (err, data)=> {
if(err) {
throw err
}
console.log(data)
fs.readFile('/data/c.txt', 'utf8', (err, data)=> {
if(err) {
throw err
}
console.log(data)
})
})
})
为了解决以上编码方式带来的问题(回调地狱嵌套),所以在ES6中新增了一个API:promise
-
Promise的英文就是保证,承诺的意思
-
Promise容器中存放了一个任务
-
有三种状态,Pending, Resolved, Rejected,成功了状态就从Pending -> Resolved,失败了就从 Pending -> Rejected
创建一个Promise容器
-
promise容器一旦创建,就开始执行里面的代码
let p1 = new Promise((resolve, reject) => {
// 这是一个异步任务
fs.readFile('/data/a.txt', 'utf8', (err, data) => {
if(err) {
// 失败了,承诺容器中的任务失败了
// 把容器的Pending状态改成Rejected
// 这里调用的resolve调用的第二个function
reject(err)
}else {
// 承诺容器的任务成功了
// 把容器的Pending状态改成Resolve
// 这里调用的resolve调用的第一个function
resolve(data)
}
})
})
// 当p1成功了,然后可以调用then做指定的动作
// then方法接收的function就是容器中的resolve
p1.then(data => {
console.log(data)
},err => {
console.log(err)
})
解决异步编程嵌套问题
let p1 = new Promise((resolve, reject) => {
fs.readFile('/data/a.txt', 'utf8', (err, data) => {
if(err) {
reject(err)
}else {
resolve(data)
}
})
})
let p2 = new Promise((resolve, reject) => {
fs.readFile('/data/b.txt', 'utf8', (err, data) => {
if(err) {
reject(err)
}else {
resolve(data)
}
})
})
p1.then(data => {
console.log(data)
// 当前函数中 return 的结果就可以在后面的then中function 接收到(return 什么接收到就是什么,没有就会收到undefined)
// 当return 一个Promise对象的时候,后面的then中的方法的第一个参数会作为p2 的resolve方法来调用
return p2
},err => {
console.log(err)
})
.then(data => {
console.log(data)
},err => {
console.log(err)
})
Promise的catch方法
catch方法算是then方法的一个语法糖,只能指定失败的回调
14.Set
ES6 提供了新的数据结构Set(集合),它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,所以可以使用扩展运算符和for of进行遍历
声明Set:let s = new Set([]) 可传入一个可迭代对象
let s = new Set(['xx','yy','zz','aa','xx']) // {'xx','yy','zz','aa'},Set会自动去重
api:
-
size 元素个数,是一个属性
-
add() 添加新的元素
-
delete() 删除一个元素
-
clear() 清空集合
15. Map
ES6 提供了Map数据结构,他类似于对象,也是键值对的集合,但是键的范围不限于字符串,各种类型的值(包括对象)都可以当作键,Map也实现了iterator接口,可以使用扩展运算符和for of进行遍历
声明:let m = new Map()
api:
-
size 元素个数,是一个属性
-
set(key, value) 添加一个键值对,key可以是任意数据类型
-
delete(map.get(key)) 删除一个元素
-
clear() 清空Map
16.class类
ES6提供了更接近传统语言的写法,引入Class类这个概念,作为对象的模板,通过Class关键字,可以定义类,ES6的class可以看作一个语法糖,他的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰,更像面向对象的写法而已
使用class关键字来声明类 class Phone{}
class Phone {
custructor(brand, price) { // 构造器
this.brand = brand
this.price = price
}
call (){} // 定义方法,只能使用es6的语法
}
使用static关键字来声明类里面的静态成员,静态成员只有类内部能够访问,实例对象无法访问静态成员
class Phone {
static name = '手机'
static change() {}
}
es6类的继承
class Son extends Parent {
custructor(brand, price, color, size){
super(bradn, price) // 相当有调用了父类的构造函数 ==> Phone.call(this, brand, price)
this.color = color
this.size = size
}
photo() {}
playGanme() {}
}
继承之后 父类的方法会在子类的原型链上
子类可以对父类方法的重写,重写同名方法后,实例对象调用方法会是子类的方法
class种getter和setter的设置
class Phone{
get price(){ // 当price属性被读取时会自动调用getter
console.log('price属性被读取了')
}
set price(newVal){ // 当price属性被修改时会自动调用setter
console.log('price属性被修改了,修改成了' + newVal)
}
}
17. 数值扩展
-
Number.EPSILON 是JS表示的最小精度, 接近2.22E-16,可以实现小数的运算精度问题
// 在JS中,小数运算 0.1 + 0.2 !== 0.3 // 我们可以定义一个方法,如果两个数差值 < number.EPSILON的话,我们就认为他是相等的 function equal(a, b) { if(Math.abs(a-b) < Number.EPSILON) { return true } else { return false } }
-
进制
// 二进制0b开头,八进制0o开头,十六进制0x开头 let b = 0b1010 // 10 let o = 0o777 // 511 let x = 0xff // 255
-
Number.isFinite 用于检测一个数是不是有限数
-
Number.isNaN 用于检测一个数值是否为NaN
-
Number.parseInt Number.parseFloat 字符串转整数
-
Number.isInteger 用于检测一个数值是不是整数
-
Number.trunc 用于把数字的小数部分抹掉
-
Number.sign 用于判断一个数到底是正数 负数 还是0 正数返回1 0返回0 负数返回-1
18.对象方法扩展
-
Object.is 判断两个值是否相等 该方法判断NaN和NaN,返回true
-
Object.assign 对象的合并
const obj = { host: 'localhost', port: 3306, name: 'root', pass: 'root' } const obj2 = { host: 'http://atguigu.com', port: 33060, name:'atguigu.com', pass:'iloveyou' } console.log(Object.assign(obj, obj2)) // 如果属性名不同则合并,要是一样就后者覆盖前者,合并的对象为浅拷贝
-
Object.setPrototypeOf 设置原型对象
-
Object.getPrototypeOf 获取原型对象
const school = { name: '尚硅谷' } const cities = { city: ['北京', '上海', '深圳'] } Object.setPrototypeOf(school, cities) // 给school设置原型对象 console.log(school)
19. ES6模块化
-
指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来
-
好处:1. 防止命名冲突 2. 代码复用 3. 高维护性
-
ES6之前的模块化:
-
CommonJS => Node.js
-
AMD => requireJS
-
CMD => sea.JS
-
-
ES6模块化语法:由两个命令构成:export 和 import
-
export 用于规定模块的对外接口
-
import 用于输入其他模块提供的功能
-
-
模块中3种暴露方式:1. export const xxx = 'xxx' 分别暴露 2.export {} 统一暴露 3. export default {} 默认暴露
-
模块中3种引入方法:1. import * as m1 from 'xxx' 通用引入 2.import {xx, yy} from 'xxx' 结构赋值引入,针对分别暴露和统一暴露 3.import m3 from 'xxx' 简便引入,针对默认暴露
20.Proxy和Reflect
Proxy即代理,可以代理数据(对象/数组/方法)提供13种方法拦截数据(Object.defineProperty只有两种方法)
Reflect即反射,提供了13种方法反射数据,和Proxy一一对应
Proxy构造函数可传入两个参数
-
target:目标对象
-
handler:具体操作
new Proxy(target, {
// 针对数据的拦截
get set has deleteProperty
// 遍历的拦截
ownKeys
// 属性描述器的拦截
getOwnPropertyDescriptor defineOwnProperty
// 是否可以扩展
isExtensible preventExtensible
})
ES7
1.数组includes方法
如果包含返回true,不包含就返回false
const mingzhu = ['西游记', '红楼梦', '三国演义', '水浒传']
console.log(mingzhu.includes('西游记')) // true
2.幂运算**
ES7 提供了幂运算符
2 ** 10 = 1024相当于Math.pow(2, 10)
ES8
1.async 和 await
async 和 await 两种语法结合可以让异步代码像同步代码一样
async表达式
在函数声明前面加上async修饰符来定义一个async函数,这个函数返回一个Promise对象,如果函数return一个字符串,则async返回一个成功的promise,如果throw Error,则async返回的就是一个失败的promise,如果return一个Promise对象,那么async返回的就是这个Promise状态的值
await表达式
await要放在async里面,await右侧的表达式一般为promise对象,await返回的是promise成功的值,await的promise失败了就会抛出异常,需要通过try..catch捕获处理
function sendAJAX(url) {
return new Promise((resolve, reject) => {
const x = new XMLHttpRequest();
x.open('GET', url)
x.send()
x.onreadystatechange = function() {
if(x.readyState === 4){
if(x.status >= 200 && x.status < 300) {
resolve(x.response)
} else {
reject(x.status)
}
}
}
})
}
async function main(){
// 实现异步编程,类似于同步编程
let result = await sendAJAX('url')
let result = await sendAJAX('url2')
}
2. 对象方法扩展
-
Object.values() 返回一个给定对象的所有可枚举值的数组
-
Object.entries() 返回一个给定对象自身可遍历属性[key, value]数组
-
Object.getOwnPropertyDescriptors() 返回指定对象所有自身属性的描述对象(writable,configurable,enumerable)
ES9
1. 对象的剩余参数和扩展运算符
function connent({host, port, ...user}){ // 剩余参数会存在user对象种
xxxx
}
const mangseng = {...tianyinbo, ...jinzhongzhao, ...tianleipo, ...menglongbaiwei} // 里面四个对象会被展开到mangseng中去
2.正则扩展-命名捕获分组
// 正则命名捕获
let str = '<a herf="www.baidu.com">百度</a>'
const reg = /<a href="(.*)">(.*)<\/a>/ // 提取url和标签文本
const result = reg.exec(str) // 返回一个数组,0:匹配的字符串 1:捕获的第一位 2:捕获的第二位
// 正则命名捕获分组
const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/ // 使用?<>分组,值会存在group对象里面
3.正则扩展-反向断言
// 正则正向断言
let str = 'JS5211314你知道吗555啦啦啦'
const reg = /\d+(?=啦)/ // 匹配后面跟着啦字的数字字符串
const result = reg.exec(str)
// 正则反向断言
const reg = /\(?<=啦)d+/
4.dotAll模式
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs // 正则后面加一个s,表示dotAll模式,这是.就能匹配任意字符
ES10
1.对象扩展方法
-
Object.fromEntries() 将二位数组转换成为对象,是Object.entries的逆运算
2.字符串扩展方法
-
trimStart 清除字符串左侧空白
-
trimEnd 清除字符串右侧空白
3.数组的扩展方法
-
flat 将多维数组转化为低维的数组
-
flatMap 将多维数组转化为低维的数组在进行map操作
ES11
1.私有属性
class类里面定义私有属性,不能被实例访问,只能在类的内部用
class Person {
// 私有属性
#age
#weight
custructor(name, age, weight) {
this.name = name
this.#age = age
this.#weight = weight
}
}
2.Promise.allSettled
接收一个promise数组参数
返回的结果始终是成功的,值是数组里面所有promise执行的结果
与Promise.all的区别
-
Promise.allSettled始终返回成功,all要数组里大的promise的执行结果全部成功,才会返回成功,否则返回失败
-
Promise.allSettled返回数组里面promise的执行结果,all要数组里的promise全部执行成功,才会返回全部的执行结果,否则返回失败的执行结果
3.String.prototype.matchAll
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs
const result = str.matchAll(reg) // 匹配全部符合reg的字符串,并存入一个数组里
4.可选链操作符
免去我们去层层判断有没有传入
function main(config){
// 之前的写法
const dbHost = config && config.db && config.db.host
// 可选链写法
const dbHost = config?.db?.host
}
5.动态import
ES11提供了import函数来进行动态引入,返回值是一个promise对象,成功就返回一个module对象(导出来的module)
不在页面加载时import,等要调用的时候在import,不影响加载的效率
6.Bigint
大整形 声明:let n = 521n / let n = BigInt(123)
可以做大数值运算
let max = Number.Max_SAFE_INTEGER;
console.log(BigInt(max) + BigInt(2)) // 大整形只能和大整形运算,不能和原始类型运算
7.绝对全局对象globalThis
ES11提供了绝对全局对象globalThis始终指向全局,浏览器指向window,Node指向global