一、ES7新特性
1.1 Array.prototype.includes()
includes方法用来检测数组中是否包含某个元素,返回布尔类型值。
const mingzhu = ['西游', '三国', '水浒']
console.log(mingzhu.includes('西游')) // true
console.log(mingzhu.includes('红楼')) // false
它和原先的indexOf的区别在于,indexOf返回的是一个数组下标,如果不存在返回-1。
1.2 **
ES7新增了**表示求次方
console.log(2 ** 10) // 1024
console.log(Math.pow(2, 10)) // 1024
二、ES8新特性
2.1 async
- async函数的返回值为promise对象
- promise对象的结果由async函数执行的返回值决定
2.2 await表达式
- await必须写在async函数中
- await右侧的表达式一般为promise对象
- await返回的是promise成功的值
- await的promise失败了,就会抛出异常,需要通过try…catch捕获处理
// 创建promise对象
const p = new Promise((resolve, reject) => {
resolve("用户1数据")
// reject("失败了1!")
})
// await 要放在 async 函数中
async function main() {
try {
let result = await p
console.log(result);
} catch (e) {
console.log(e);
}
}
// 调用函数
main()
2.3 实例:async和await结合读取文件
const fs = require("fs");
// 读md1
function readmd1() {
return new Promise((resolve, reject) => {
fs.readFile("./resources/markdown1.md", (err, data) => {
// 如果失败
if (err) reject(err);
// 如果成功
resolve(data);
});
});
}
// 读md2
function readmd2() {
return new Promise((resolve, reject) => {
fs.readFile("./resources/markdown2.md", (err, data) => {
// 如果失败
if (err) reject(err);
// 如果成功
resolve(data);
});
});
}
// 读md3
function readmd3() {
return new Promise((resolve, reject) => {
fs.readFile("./resources/markdown3.md", (err, data) => {
// 如果失败
if (err) reject(err);
// 如果成功
resolve(data);
});
});
}
// 声明一个 async 函数
async function main() {
// 获取md1内容
let md1 = await readmd1();
// 获取md2内容
let md2 = await readmd2();
// 获取md3内容
let md3 = await readmd3();
console.log(md1.toString());
console.log(md2.toString());
console.log(md3.toString());
}
main();
2.4 实例:async和await封装AJAX请求
// 发送 AJAX 请求, 返回的结果是 Promise 对象
function sendAJAX(url) {
return new Promise((resolve, reject) => {
// 1.创建对象
const x = new XMLHttpRequest()
// 2. 初始化
x.open('GET', url)
// 3. 发送
x.send()
// 4.事件绑定
x.onreadystatechange = function () {
if (x.readyState === 4) {
if (x.status >= 200 && x.status < 300) {
// 成功了
resolve(x.response)
} else {
// 如果失败
reject(x.status)
}
}
}
})
}
// promise then 方法测试
// sendAJAX("https://api.apiopen.top/getJoke").then(value => {
// console.log(value);
// }, reason => { })
// async 与 await 测试
async function main() {
// 发送 AJAX 请求
let result = await sendAJAX("https://api.apiopen.top/getJoke")
console.log(result);
}
main()
2.5 Object.values()、.keys()和entries()
- Object.keys()方法返回一个给定对象的所有可枚举属性键的数组
- Object.values()方法返回一个给定对象的所有可枚举属性值的数组
- Object.entries()方法返回一个给定对象自身可遍历属性[key,value]的数组
// 声明对象
const school = {
name: 'wjr',
study: ['es6', 'js', 'node']
}
// 获取对象所有的键
console.log(Object.keys(school)); // ['name', 'study']
// 获取对象所有的值
console.log(Object.values(school)); // ['wjr', ['es6', 'js', 'node']]
// 获取对象的所有键值对
console.log(Object.entries(school)); // [['name', 'wjr'], ['study', ['es6', 'js', 'node']]]
// entries方法可以用来创建Map
const m = new Map(Object.entries(school))
console.log(m.get('study')); // ['es6', 'js', 'node']
2.6 Object.getOwnPropertyDescriptors
该方法返回指定对象所有自身属性的描述对象
三、ES9新特性
3.1 针对对象的spread扩展运算符
Rest参数与spread扩展运算符在ES6中已经引入,不过ES6中只针对与数组,在ES9中为对象提供了像数组一样的rest参数和扩展运算符。
function connect({host, port, ...user}){
console.log(host)
console.log(port)
console.log(user)
}
connect({
host: '127.0.0.1',
port: 3306,
username: 'root',
password: 'root',
type: 'master'
)
// connect函数中接收的对象会正常接收前两个参数,而将后面的username,password,type三个参数一起存到user对象中
3.2 正则扩展-命名捕获分组group
ES9为正则匹配新增了组的概念
// 声明一个字符串
let str = '<a href="http://www.baidu.com">百度</a>'
// [未添加组]使用正则提取 url 与 文本标签
const reg1 = /<a href="(.*)">(.*)<\/a>/
// 执行
const result = reg1.exec(str)
// 输出的结果是一个数组 索引0的是整个正则匹配到的结果,1是第一个小括号匹配到的结果 2是第二个小括号匹配到的结果
console.log(result); // ['<a href="http://www.baidu.com">百度</a>', 'http://www.baidu.com', '百度']
console.log(result[1]); // http://www.baidu.com
console.log(result[2]); // 百度
// [添加组]使用正则提取 url 与 文本标签
const reg2 = /<a href="(?<url>.*)">(?<text>.*)<\/a>/
const result2 = reg2.exec(str)
console.log(result2);
console.log(result2.groups.text);
console.log(result2.groups.url);
如上图所示,可以看到明显的正则分组,并且可以将匹配到的值重新命名,使用属性的方式去获取,防止了正则变化时,数字位置变化的问题。
3.3 正则扩展-反向断言
断言:断言(Assertion)是一个对当前匹配位置之前或之后的字符的测试, 它不会实际消耗任何字符,所以断言也被称为“非消耗性匹配”或“非获取匹配”。
正向断言的意思是:当前位置后面的字符串应该满足断言,但是并不捕获,仅此而已。
反向断言和正向断言行为一样,只是方向相反,
// 声明字符串
let str = 'JS456123你知道么555啦啦啦'
// 正向断言
const reg1 = /\d+(?=啦)/
const result1 = reg1.exec(str)
console.log(result1); // ['555']
// 反向断言
const reg2 = /(?<=么)\d+/
const result2 = reg2.exec(str)
console.log(result2); // ['555']
3.4 正则扩展-dotAll模式
dot .:是一种元字符,可以实现匹配除换行符以外的任意单个字符。
如何使用dotAll模式:正则表达式后面增加字符s,这样表达式内的dot(.)就能匹配任意字符了。
如若要实现全局匹配,需要在s前面加个g,表示全局匹配。
let str = `
<ul>
<li>
<a>肖申克的救赎</a>
<p>上映时间:1994-09-10</p>
</li>
<li>
<a>阿甘正传</a>
<p>上映时间:1994-07-06</p>
</li>
</ul>`
// 声明正则[不用dotAll]
const reg1 = /<li>\s+<a>(.*?)<\/a>\s+<p>(.*?)<\/p>/
// 执行匹配
const result1 = reg1.exec(str)
console.log(result1);
// 声明正则[使用dotAll]
const reg2 = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs // g表示全局匹配,去掉则是单个匹配
// 执行全局匹配
let result2
let data = []
while (result2 = reg2.exec(str)) {
data.push({ title: result2[1], time: result2[2] })
}
console.log(data);
四、ES10新特性
4.1 字符串方法扩展-trimstart()和trimend()
清除字符串左侧的空白符和清除字符串右侧的空白符。
4.2 数组方法扩展-flat()
flat()方法将多维数组转换为低维数组,参数表示深度,是一个数字
const arr = [1, 2, 3, [5, 6]]
console.log(arr.flat()) // [1, 2, 3, 5, 6]
const arr2 = [1, 2, 3, [5, 6, [7, 8]]]
console.log(arr.flat()) // [1, 2, 3, 5, 6, [7, 8]]
console.log(arr.flat(2)) // [1, 2, 3, 5, 6, 7, 8]
4.3 数组方法扩展-flatMap()
flatMap方法相当于arr.flat()和arr.map()相结合。
const arr = [1, 2, 3, 4]
const result = arr.map(item => item * 10) // map实现对所有数据操作
console.log(result) //
const result1 = arr.map(item => [item * 10])
console.log(result) // [[10], [20], [30], [40]]
// 使用flatMap()
const result2 = arr.flatMap(item => [item * 10])
console.log(result) // [10, 20, 30, 40]
4.4 Symbol.prototype.description
// 创建 Symbol
let s = Symbol('Eson')
console.log(s.description) // Eson
五、ES11新特性
5.1 私有属性
class Person {
// 共有属性
name
// 私有属性
#age
#weight
// 构造方法
constructor(name, age, weight) {
this.name = name
this.#age = age
this.#weight = weight
}
intro() {
console.log(this.name);
console.log(this.#age);
console.log(this.#weight); // 类内部可以输出私有属性
}
}
// 实例化
const girl = new Person('小红', 18, '45kg')
console.log(girl.name); // 小红
// console.log(girl.#age); // 会报错 无法输出私有属性
girl.intro(); // 小红 18 45kg
5.2 Promise.allSettled
根据选中的Promise对象,调用Promise.allSettled方法,始终返回一个reslove的Promise对象,Promise对象中的结果根据选中的Promise对象来判断是resolve还是rejected。
all和allSettled的区别:
all只有全部Promise对象都是成功才返回reslove,只要有一个失败就返回rejected,而allSettled返回的Promise对象一定是成功的,不管是否有失败的对象。
all和allSettled都在批量异步的场景下使用,如果每个异步都想要一个结果那就使用allSettled,如果每个异步任务都要求成功才能往下执行那就使用all。
// 声明两个promise对象
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('商品数据')
}, 1000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('出错拉')
}, 1000);
})
// 调用 allsettled 方法
const result1 = Promise.allSettled([p1, p2])
const result2 = Promise.all([p1, p2])
console.log(result1);
console.log(result2);
5.3 String.prototype.matchAll()批量匹配
let str = `
<ul>
<li>
<a>肖申克的救赎</a>
<p>上映时间:1994-09-10</p>
</li>
<li>
<a>阿甘正传</a>
<p>上映时间:1994-07-06</p>
</li>
</ul>`
// 声明正则
const reg1 = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/sg
// 调用方法
const result = str.matchAll(reg1)
console.log(result); // 返回的结果是一个可迭代对象
for (let v of result) {
console.log(v);
}
// 使用扩展运算符展开
const arr = [...result]
console.log(arr);
5.4 可选链操作符?.
可选链操作符(?.)会先判断?前面的是否存在,存在则继续执行.后面的属性。
function main(config) {
// 这样会存在一个问题,如果传入的参数对象为空的话就会报错
// const dbHost = config.db.host
// 因此根据传入的参数对象进行判断,如果参数对象存在就获取他的db属性,如果db存在就获取db中的host
// const dbHost = config && config.db && config.db.host;
// 使用可选链操作符能够做到一样的效果
const dbHost = config?.db?.host
console.log(dbHost);
}
main() // undefined
main({
db: {
host: '192.168.1.100',
username: 'root'
},
cache: {
host: '192.168.1.200',
username: 'admin'
}
}) // 192.168.1.100
5.5 大整型
// 大整型
let n = 521n
console.log(n, typeof (n)); // 521n BigInt
// 函数
let m = 123
console.log(BigInt(m)); // 123n
// console.log(BigInt(1.2)); // 报错
// 大整型运算
let max = Number.MAX_SAFE_INTEGER // js最大安全整数
console.log(max); // 9007199254740991
console.log(max + 1); // 9007199254740992
console.log(max + 2); // 9007199254740992 出现了无法继续加的情况
// 使用大整型就能进行相关运算
console.log(BigInt(max)); // 9007199254740991n
console.log(BigInt(max) + BigInt(1)); // 9007199254740992n
console.log(BigInt(max) + BigInt(2)); // 9007199254740993n