ES7
Array.prototype.includes
概述
Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值;
判断数组中是否包含某元素,语法:arr.includes(元素值);
代码
let arr = [1,2,3,4,5]; console.log(arr.includes(1));//true
指数操作符
概述
在 ES7 中引入指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同;
幂运算的简化写法,例如:2的10次方:2**10;
代码
console.log(Math.pow(2,10)) //1024 console.log(2**10);//1024
ES8
async 和 await
可以参考下面网址的教程
概述
async 和 await 两种语法结合可以让异步代码看起来像同步代码一样;简化异步函数的写法;
async函数
1.async 函数的返回值为 promise 对象;
2.promise 对象的结果由 async 函数执行的返回值决定;
代码
1.return返回的是非promise对象,,则async返回成功的promise,且该promise对象中的状态为成功,值为返回值。
async function fn(){ return "hello"; } const result = fn(); console.log(result);
2.函数中抛出错误的话,返回的也是promise,不过状态为错误!
async function fn(){ throw new Error("新错误!!"); } const result = fn(); console.log(result);
3.函数return的是promise对象的话,async返回的promise对象与return的promise对象一致!
async function fn(){ return new Promise((resolve,reject)=>{ resolve("返回的promise是成功的promise!!"); }) } const result = fn(); console.log(result);
若返回的promise是reject,则async返回的也是失败类型的promise
async function fn(){ return new Promise((resolve,reject)=>{ reject("失败了!!"); }) } const result = fn(); console.log(result);
await表达式
概述
1.await 必须写在 async 函数中;
2.await 右侧的表达式一般为 promise 对象;
3.await 返回的是 promise 成功的值;
4.await 的 promise 失败了, 就会抛出异常, 需要通过 try...catch 捕获处理
代码
1.返回的promise是成功的
// async函数 + await表达式:异步函数 // 创建Prmise对象 const p = new Promise((resolve,reject)=>{ resolve("成功啦!"); }) async function fn(){ // await 返回的是 promise 成功的值 let result = await p; console.log(result); // 成功啦! } fn();
2.返回的promise是失败的话,就需要用try...catch来捕获
const p = new Promise((resolve,reject) => { reject("返回的promise是失败的!") }) async function main(){ try{ let result = await p; console.log(result); }catch(e){ console.log("捕获到异常了!") console.log(e); } } main();
async和await结合案例
案例1----读取文件
// 导入模块 const fs = require("fs"); // 读取 function readText() { return new Promise((resolve, reject) => { fs.readFile("../resources/text.txt", (err, data) => { //如果失败 if (err) reject(err); //如果成功 resolve(data); }) }) } function readTest1() { return new Promise((resolve, reject) => { fs.readFile("../resources/test1.txt", (err, data) => { //如果失败 if (err) reject(err); //如果成功 resolve(data); }) }) } function readTest2() { return new Promise((resolve, reject) => { fs.readFile("../resources/test2.txt", (err, data) => { //如果失败 if (err) reject(err); //如果成功 resolve(data); }) }) } //声明一个 async 函数 async function main(){ //获取为学内容 let t0 = await readText(); //因为返回的都是promise对象,所以可以直接用await读取promise成功状态下的值 //获取插秧诗内容 let t1 = await readTest1(); // 获取观书有感 let t2 = await readTest2(); console.log(t0.toString()); console.log(t1.toString()); console.log(t2.toString()); } main();
案例2----发送ajax请求
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<=299){ // 成功 resolve(x.response); }else{ // 失败 reject(x.status); } } } }); } async function main(){ let result = await sendAjax("https://api.apiopen.top/getJoke"); console.log(result); } main();
ES9
spred拓展运算符与rest参数
概述
Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符;
1.rest参数的使用场景
function connect({host,port,username,password}){//这里参数接受的是一个对象 console.log(host); console.log(port); console.log(username); console.log(password); } connect({ host:'127.0.0.1', port:3306, username:'root', password:'root' });
参数接受的是一个对象时,按照这样的写法没有什么问题,效果如下:
rest参数可以把剩下的参数整合到一个对象中,比如把username和password整合到user对象中,写法如下:
function connect({host,port,...user}){ console.log(host); console.log(port); console.log(user);//这里的user就是一个对象 } connect({ host:'127.0.0.1', port:3306, username:'root', password:'root' });
结果如下
2.拓展运算符使得对象合并
const skillOne = { q: '天音波' } const skillTwo = { w: '金钟罩' } const skillThree = { e: '天雷破' } const skillFour = { r: '猛龙摆尾', z: '胡说八道' } const mangseng = { ...skillOne, ...skillTwo, ...skillThree, ...skillFour }; console.log(mangseng)
结果:
正则拓展,命名捕获分组
概述
ES9 允许命名捕获组使用符号『?』,这样获取捕获结果可读性更强;
代码
普通方式提取正则表达式中的必要字符串可以通过数组下标的形式:
let str = '<a href="http://www.baidu.com">訾博</a>'; //需求:提取url和标签内文本 const reg = /<a href="(.*)">(.*)<\/a>/; const result = reg.exec(str); console.log(result); console.log(result[1])//http://www.baidu.com
结果
不过这么提取会有一个弊端,就是数组下标作为提取的依据,变量名的表面意义并没有用上,即我们调用数组时有可能并不知道数组中的第一个元素对应的是哪个变量。
这时我们就可以对正则提取出来的元素进行命名,这样更方便提取,被命名的元素都会出现在groups中。
let str = '<a href="http://www.baidu.com">訾博</a>'; const reg1 = /<a href="(?<url>.*)">(?<text>.*)<\/a>/; const result1 = reg1.exec(str); console.log(result1); //通过变量名提取字符串 console.log(result1.groups.url); console.log(result1.groups.text); //当然也可以通过数组名来提取字符串 console.log("通过数组调用") console.log(result1[1]) console.log(result1[2])
结果如下:
正则拓展,反向断言
概述
ES9 支持反向断言,通过对匹配结果前面的内容进行判断,对匹配进行筛选,这就是反向断言。正向断言就是根据后面的内容进行判断。
代码
需求:我们想要提取啦啦啦前面的,你知道么后面的555,该如何提取?通过正则表达式
1.使用正向断言
let str = "JS5201314你知道么555啦啦啦"; const reg = /\d+(?=啦)/; // 前面是数字后面是啦 const result = reg.exec(str); console.log(result);
2.使用反向断言
let str = "JS5201314你知道么555啦啦啦"; const reg1 = /(?<=么)\d+/; // 后面是数字前面是么 const result1 = reg.exec(str); console.log(result1);
正则拓展:dotAll 模式
概述
正则表达式中点.匹配除回车外的任何单字符,标记『s』改变这种行为,允许行终止符出现;
代码
想取出电影名和上映日期
let str = ` <ul> <li> <a>肖生克的救赎</a> <p>上映日期: 1994-09-10</p> </li> <li> <a>阿甘正传</a> <p>上映日期: 1994-07-06</p> </li> </ul> `; //旧写法 const reg = /<li>\s+<a>(.*?)<\/a>\s+<p>(.*?)<\/p>/;//加\s是为了匹配换行符,这点就比较讨厌 // const reg = /<li>.*?<a>(?<name>.*?)<\/a>.*?<p>(?<time>.*?)<\/p>/sg;;若使用命名捕获分组的话 const result=reg.exec(str); console.log(result)
结果如下:
使用dotAll的话,匹配换行符可以直接使用.*?来进行,十分方便!
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs;//末尾加上gs代表全局匹配 let result; let data = []; while(result = reg.exec(str)){ data.push({title:result[1],time:result[2]}); } console.log(data);
结果如下:
ES10
Object.fromEntries将二维数组或者map转换为对象
1.将二维数组转换为对象
const result = Object.fromEntries([ ["name","訾博"], ["age",24], ]); console.log(result);
结果:
2.将map转换为对象
const m = new Mao(); m.set("name","阿福"); m.set("age",26); const result = Object.fromEntries(m); console.log(result);
结果:
这里的方法和ES8中的方法Object.entries()有对应,ES8中的Object.entries()将对象转换为二维数组
const afu={ name:"阿福", age:"22" }; const arr = Object.entries(afu); console.log(arr);
trimStart和trimEnd
在之前的语法中trim可以清楚字符串左侧和右侧的空白字符,而trimStart是指定清除左侧的,trimEnd是指定清除右侧的。
let str = " zibo "; console.log(str.trimLeft()); console.log(str.trimRight()); console.log(str.trimStart()); console.log(str.trimEnd()); console.log(str.trim())
结果如下:
数组拓展的方法:flat
用于将多维数组转化为低维数组
flat(),里面传递的参数默认为1,参数表明把数组降低多少维度。
const arr=[1,2,3,4[5,6[7,8,9]]]//这是一个三维数组 //如果想降低一维成为二维数组,则直接调用flat即可 console.log("二维数组:") console.log(arr.flat()); console.log("一维数组:") console.log(arr.flat(1));
ES11
对象的私有属性
概述
对象中的属性前面加上#后,就代表是私有属性,这样就不能通过外部直接调用来获取私有属性了
class Person{ name; #age; #weight; constructor(name,age,weight){ this.name=name; this.#age=age; this.#weight=weight; } getAge(){ return #age; } } //实例化 const girl = new Person('小红',18,'45kg'); console.log(girl.name);//可以正常打印 //但如果直接读取私有属性的话,就会报错 console.log(girl.#age);
会报错:
把读取私有属性的语句注释掉之后:
读取私有属性可以通过类内部的方法进行调用:
console.log(girl.getAge());
字符串拓展: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 reg = /<li>.*?<a>(?<name>.*?)<\/a>.*?<p>(?<time>.*?)<\/p>/sg; const result = str.matchAll(reg); console.log(result)
得到的是一个可迭代对象
对于这个可迭代对象,我们可以使用for of进行遍历,同样也可以使用拓展运算符讲其转换为数组
const result = str.matchAll(reg); let arr = [...result]; console.log(arr)
也可以迭代,使用for..of..
可选链操作符
概述
如果存在则往下走,省略对对象是否传入的层层判断;
代码
假如一个函数接受的参数是一个配置对象,我们想读出配置对象里的某个属性,那么使用js的话需要层层判断,首先需要判断配置对象是否传入接着再来判断对象里的属性是否初始化等等...
1.传统写法
function main(config){ const dbHost = config && config.db && config.db.host;//只有前面的都存在才会读取config.db.host console.log(dbHost); } main({ db:{ host:`192.168.1.100`, username:`root` }, cache:{ host:`192.168.1.200`, username:`admin` } })
如果不判断,就直接打印的话,若传入的对象没有该属性,就会报错
function main(config){ const dbHost =config.db.host; console.log(dbHost); } main({ cache:{ host:`192.168.1.200`, username:`admin` } })
若是先前有判断的写法的话,就会显示undefined,并不会报错!
2.使用可选链操作符就简便的多
(1)若没有相应的属性
function main(config){ const dbHost = config?.db?.host; console.log(dbHost); } main({ cache:{ host:`192.168.1.200`, username:`admin` } })
(2)若有相应的属性
function main(config){ const dbHost = config?.db?.host; console.log(dbHost); } main({ db:{ host:`192.168.1.100`, username:`root` }, cache:{ host:`192.168.1.200`, username:`admin` } })
成功打印:
动态import
概述
实现模块的懒加载,用到的时候再导入,传统的import是静态导入,即加载import语句的时候就把对应的模块导入进来了。
代码
hello.js:
export function hello(){ alert('Hello'); }
html文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>动态 import </title> </head> <body> <button id="btn">点击</button> <script src="app.js" type="module"></script> </body> </html>
1.静态导入方式
app.js
import * as m1 from "./hello.js"; // 传统静态导入 const btn = document.getElementById('btn'); btn.onclik = function(){ m1.hello(); }
2.动态导入方式
app.js
btn.onclick = function(){ import('./hello.js').then(module => {//动态导入返回的是一个promise对象 module.hello(); }); }
BigInt
概述
更大的整数,使用方法是声明时在普通的数字后面加n即可,也可以使用BigInt()函数来讲普通类型的数字转换为大整型的数字。
代码
1.声明
let n =521n; console.log(n,typeof(n));
2.使用函数转换普通数字
let n =123; console.log(BigInt(n)); console.log(BigInt(1.2));//不能转换浮点型数字,这样会报错!
3.BigInt主要用于更大整数的运算
let max = Number.MAX_SAFE_INTEGER;//9007199254740991 console.log(max); console.log(max + 1); console.log(max + 2); console.log(BigInt(max)) //console.log(BigInt(max)+1) 这么写会报错,因为BigInt类型的值无法和普通int做运算,必须把所有操作数都转换为BigInt才可以进行运算 console.log(BigInt(max) + BigInt(1)); console.log(BigInt(max) + BigInt(2));
golbalThis对象
概述
始终指向全局对象window
代码
console.log(gobalThis);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY