ES7
一、indexOf方法
1、在数组中
indexOf方法用于查找一个元素在数组中的位置。如果该元素在数组中存在,则返回其第一个出现的索引(从0开始计数);如果不存在,则返回-1。
语法:
array.indexOf(searchElement[, fromIndex])
searchElement:要在数组中查找的元素。fromIndex(可选):表示从该索引处开始查找,默认为0。如果索引值大于或等于数组的长度,则整个数组都会被搜索。如果为负值,则将其视为从数组末尾开始的第几位(但不是从-1开始计算,而是从数组长度减1开始,然后减去该负值,如果计算出的索引小于0,则整个数组都会被搜索)。
示例:
let array = [2, 5, 9, 1, 2];
console.log(array.indexOf(2)); // 输出: 0
console.log(array.indexOf(7)); // 输出: -1
console.log(array.indexOf(2, 1)); // 输出: 4,因为从索引1开始查找,第二个2的索引是4
2、在字符串中
indexOf方法在字符串中,indexOf方法用于查找一个子字符串在字符串中首次出现的位置(索引)。如果该子字符串存在,则返回其第一个字符的索引;如果不存在,则返回-1。
语法:
string.indexOf(searchValue[, fromIndex])
searchValue:要在字符串中查找的子字符串。fromIndex(可选):表示从该索引处开始查找,默认为0。如果索引值大于或等于字符串的长度,则整个字符串都会被搜索。如果为负值,则将其视为从字符串末尾开始的第几位(但计算方式与数组略有不同,具体为:fromIndex = string.length + fromIndex,如果计算出的索引小于0,则整个字符串都会被搜索)。但需要注意的是,在字符串中,fromIndex为负数的情况并不常用,且可能因浏览器或JavaScript引擎的不同而有所差异。
示例:
let str = "Hello, world!";
console.log(str.indexOf("world")); // 输出: 7
console.log(str.indexOf("o")); // 输出: 4,因为"o"在字符串中首次出现的索引是4
console.log(str.indexOf("o", 5)); // 输出: 8,因为从索引5开始查找,"o"在字符串中第二次出现的索引是8
3、注意事项
indexOf方法使用严格相等运算符(===)来比较元素或子字符串。因此,对于数组来说,如果数组元素是对象,那么即使两个对象的内容相同,indexOf方法也会返回-1,因为它们在内存中的引用是不同的。- 对于字符串来说,
indexOf方法是区分大小写的。例如,str.indexOf("Hello")和str.indexOf("hello")的结果是不同的。 - 当在数组中查找
NaN时,indexOf方法会失败,因为NaN与任何值(包括它自身)都不相等。在这种情况下,可以使用Array.prototype.includes()方法,它认为两个NaN是相等的。
includes 方法是 JavaScript 数组和字符串对象的一个方法,用于判断一个数组或字符串是否包含一个指定的元素或子字符串。如果包含,则返回 true;否则返回 false。
二、includes
1、数组中
在数组中,includes 方法用于检查数组是否包含某个元素,并根据情况返回 true 或 false。
语法:
valueToFind:需要查找的元素值。fromIndex(可选):表示从该索引处开始查找,默认为0。如果索引值大于或等于数组的长度,则返回false。如果为负值,则将其视为从数组末尾开始的第几位(但不是从-1开始计算,而是从数组长度减1开始,然后减去该负值,如果计算出的索引小于0,则整个数组都会被搜索)。 示例:
let array = [1, 2, 3, 4, 5];
console.log(array.includes(3)); // 输出: true
console.log(array.includes(10)); // 输出: false
console.log(array.includes(3, -2)); // 输出: true,因为从倒数第二个元素开始查找,3存在于数组中
2、字符串中
字符串中,includes 方法用于判断一个字符串是否包含另一个子字符串,并根据情况返回 true 或 false。
语法:
string.includes(searchString[, position])
searchString:需要在字符串中查找的子字符串。position(可选):表示从该索引处开始查找,默认为0。如果索引值大于或等于字符串的长度,则返回false。如果为负值,则将其视为从字符串末尾开始的第几位(但计算方式与数组略有不同,且这种用法在字符串中并不常见,因为字符串索引不允许为负数)。 示例:
let str = "Hello, world!";
console.log(str.includes("world")); // 输出: true
console.log(str.includes("o")); // 输出: true,因为"o"是子字符串,存在于字符串中
console.log(str.includes("o", 5)); // 输出: true,因为从索引5开始查找,"o"在字符串中仍然存在(出现在索引7处)
// 注意:在字符串中,通常不会使用负数的position值,因为这会导致错误或不符合预期的行为。
3、注意事项
includes方法对大小写敏感。例如,str.includes("Hello")和str.includes("hello")的结果是不同的。includes方法使用严格相等运算符(===)的等价逻辑来比较元素或子字符串。但是,对于NaN的比较,includes方法认为两个NaN是相等的,这与indexOf方法不同(indexOf方法认为NaN不等于任何值,包括它自身)。- 在数组中查找对象时,即使两个对象的内容相同(即它们的属性名和属性值都相同),
includes方法也会返回false,因为它们在内存中的引用是不同的。要比较对象的内容是否相同,需要使用其他方法(如深度比较函数)。
三、**
运算符用于计算一个数的指数幂
let a = 2;
let b = 3;
let result1 = a ** b; // 8
let result2 = 2 ** 3 ** 2; // 512
let c = 1.5;
c **= 2; // c 的值变为 2.25
ES8 async和await
ES8(ECMAScript 2017)引入了 async 和 await 关键字,它们是对 JavaScript 中处理异步操作的一种更简洁和直观的方式。这两个关键字使得异步代码看起来更像是同步代码,从而大大简化了异步编程的复杂性。
一、async 关键字
async 关键字用于声明一个异步函数。它会隐式地返回一个 Promise 对象。如果函数正常结束,则 Promise 会被解析(resolved);如果函数抛出异常,则 Promise 会被拒绝(rejected)。
如果结果不是一个 Promise类型对象,就会隐式地返回一个成功的Promise对象
async function fn(){
// 返回一个字符串
return '隐式返回成功的Promise';
// 返回的结果不是一个 Promise 类型的对象, 返回的结果就是成功 Promise 对象
}
const result = fn();
console.log(result);
返回结果设置为空,则返回一个隐式返回成功的Promise,值为undefined
async function fn(){
return ;
}
const result = fn();
console.log(result);
抛出错误, 返回的结果是一个失败的 Promise
async function fn(){
throw new Error('出错啦!');
}
设计结果是Promise对象
1、方式一
async function fn(){
return new Promise((resolve, reject)=>{
resolve('成功的数据');
// reject("失败的错误");
});
}
const result = fn();
console.log(result);
2、方式二:使用then
async function fn(){
return new Promise((resolve, reject)=>{
resolve('成功的数据');
// reject("失败的错误");
});
}
const result = fn();
//调用 then 方法
result.then(value => {
console.log(value);
}, reason => {
console.warn(reason);
})
二、await 关键字
await 关键字只能在 async 函数内部使用。它用于等待一个 Promise 完成,并返回 Promise 的结果。如果 Promise 被拒绝,则会抛出异常,可以用 try...catch 语句捕获。
1、一般使用
async function myFunction() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve('Done!'), 1000);
});
let result = await promise; // 等待 Promise 完成
alert(result); // 输出: Done!
}
myFunction();
1、使用 async 和 await 处理多个异步操作
async 和 await 使得处理多个异步操作变得更加简单。你可以使用 await 依次等待每个异步操作完成,而不需要使用嵌套的 .then() 方法。
async function fetchData() {
try {
let response1 = await fetch('https://api.example.com/data1');
let data1 = await response1.json();
let response2 = await fetch('https://api.example.com/data2');
let data2 = await response2.json();
console.log(data1, data2);
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData();
3、并行处理多个异步操作
虽然 await 会按顺序等待每个 Promise 完成,但你可以使用 Promise.all() 来并行处理多个异步操作。
async function fetchData() {
try {
let promise1 = fetch('https://api.example.com/data1').then(response => response.json());
let promise2 = fetch('https://api.example.com/data2').then(response => response.json());
let [data1, data2] = await Promise.all([promise1, promise2]);
console.log(data1, data2);
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData();
4、总结
async关键字用于声明一个返回Promise的异步函数。await关键字用于等待一个Promise完成,并返回其结果。它只能在async函数内部使用。- 使用
try...catch语句来捕获await等待的Promise被拒绝时的异常。 - 可以使用
Promise.all()来并行处理多个异步操作。async和await使得异步代码更加直观和易于理解,是现代 JavaScript 异步编程的一种重要工具。
三、对象方法扩展
1、获取所有的键Object.keys
2、获取所有的值Object.values
3、获取所有的键值对Object.entries
4、创建map
5、对象属性的描述对象
//声明对象
const school = {
name:"尚硅谷",
cities:['北京','上海','深圳'],
xueke: ['前端','Java','大数据','运维']
};
// 获取对象所有的键
console.log(Object.keys(school));
// 获取对象所有的值
console.log(Object.values(school));
// entries 获取所有的键值对
console.log(Object.entries(school));
// 创建 Map
const m = new Map(Object.entries(school));
console.log(m.get('cities'));
// 对象属性的描述对象
console.log(Object.getOwnPropertyDescriptors(school));
const obj = Object.create(null, {
name: {
//设置值
value: '尚硅谷',
//属性特性
writable: true,
configurable: true,
enumerable: true
}
});
案例
1、async和await读取文件
//1. 引入 fs 模块
const fs = require("fs");
//读取文件1
function readFile1() {
return new Promise((resolve, reject) => {
fs.readFile("./resources/文件1.md", (err, data) => {
//如果失败
if (err) reject(err);
//如果成功
resolve(data);
})
})
}
function readFile2() {
return new Promise((resolve, reject) => {
fs.readFile("./resources/文件2.md", (err, data) => {
//如果失败
if (err) reject(err);
//如果成功
resolve(data);
})
})
}
function readFile3() {
return new Promise((resolve, reject) => {
fs.readFile("./resources/文件3.md", (err, data) => {
//如果失败
if (err) reject(err);
//如果成功
resolve(data);
})
})
}
//声明一个 async 函数
async function main(){
try {
//获取文件1内容
let File1 = await readFile1();
//获取文件2内容
let File2 = await readFile2();
// 获取文件3有感
let File3 = await readFile3();
console.log(File1.toString());
console.log(File2.toString());
console.log(File3.toString());
} catch (error) {
console.error("读取文件时出错:", error.message)
}
}
main();
2、async和await发送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 < 300) {
// 成功啦
try {
const responseData = JSON.parse(x.responseText);
resolve(responseData); // 将解析后的数据传递给Promise的resolve函数
} catch (parseError) {
reject(new Error('Error parsing JSON response: ' + parseError.message));
}
} else {
// 请求失败
reject(new Error('Request failed with status: ' + x.status));
}
}
};
// 处理网络错误(如请求被中断)
x.onerror = function () {
reject(new Error('Network error occurred during the request.'));
};
});
}
// 使用示例 then
const weatherAPIUrl = 'https://www.tianqiapi.com/api/?version=v1&city=%E5%8C%97%E4%BA%AC&appid=23941491&appsecret=TXoD5e8P';
sendAJAX(weatherAPIUrl)
.then(data => {
console.log('Weather data received:', data);
// 在这里处理天气数据
})
.catch(error => {
console.error('Error fetching weather data:', error.message);
});
ES9
一、对象展开
Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组, 在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符
//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'
});
//对象合并
const skillOne = {
q: '天音波'
}
const skillTwo = {
w: '金钟罩'
}
const skillThree = {
e: '天雷破'
}
const skillFour = {
r: '猛龙摆尾'
}
const mangseng = {...skillOne, ...skillTwo, ...skillThree, ...skillFour};
console.log(mangseng)
二、正则表达式
1、有分组
//声明一个字符串
let str = '<a href="http://www.atguigu.com">尚硅谷</a>';
// //提取 url 与 『标签文本』
// 捕获
const reg = /<a href="(.*)">(.*)<\/a>/;
// //执行
const result = reg.exec(str);
console.log(result);
console.log(result[1]);
console.log(result[2]);
2、无分组(进行命名)
let str = '<a href="http://www.atguigu.com">尚硅谷</a>';
//分组命名
const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;
const result = reg.exec(str);
console.log(result.groups.url);
console.log(result.groups.text);
正则断言(正向断言、反向断言)
1、正向断言
//声明字符串
let str = 'JS5211314你知道么555啦啦啦';
//正向断言
const reg = /\d+(?=啦)/; //判断后面是不是啦
const result = reg.exec(str); //555
console.log(result);
2、反向断言
let str = 'JS5211314你知道么555啦啦啦';
//反向断言
const reg = /(?<=么)\d+/; //判断前面是不是么
const result = reg.exec(str); //555
console.log(result);
3、正则扩展-dotAll模式 dot . 元字符 除换行符以外的任意单个字符
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>/;
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs;
//执行匹配
// const result = reg.exec(str);
let result;
let data = [];
while(result = reg.exec(str)){
data.push({title: result[1], time: result[2]});
}
//输出结果
console.log(data);
ES10
一、Object.fromEntries
1、Object.fromEntries将二维数组转化为对象
2、补充:在ES8中
Object.entrie将对象转化为二维数组
//二维数组
const result = Object.fromEntries([
['name','尚硅谷'],
['xueke', 'Java,大数据,前端,云计算']
]);
//Map
const m = new Map();
m.set('name','ATGUIGU');
const result2 = Object.fromEntries(m);
console.log(result2);
//Object.entries ES8
const arr = Object.entries({
name: "尚硅谷"
})
console.log(arr);
二、trim、trimStart 与 trimEnd清除空白字符
1、trim清除两侧的空白字符
2、trimStart清除左侧的空白字符串
3、trimEnd清除右侧的空白字符串
let str = ' iloveyou ';
console.log(str);
console.log(str.trim());
console.log(str.trim().length);
console.log(str.trimStart());
console.log(str.trimStart().length);
console.log(str.trimEnd());
三、flat 与 flatMap
1、flat 将多维数组转换为低平数组
//flat 平
//将多维数组转化为低位数组
const arr = [1,2,3,4,[5,6]];
console.log(arr.flat(2));
const arr = [1,2,3,4,[5,6,[7,8,9]]];
//参数为深度 是一个数字
console.log(arr.flat(2));
2、flatMap的每个结果进行唯独的操作
const arr = [1,2,3,4];
const result = arr.flatMap(item => [item * 10]);
console.log(result);
四、Symbol.prototype.description
获取Symbol的字符串描述
//创建 Symbol
let s = Symbol('尚硅谷');
console.log(s); //Symbol(尚硅谷)
console.log(s.description); //尚硅谷
ES11
一、私有属性
在对象前面加#可以实现私有属性,使用一般获取方法会报错
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); //报错
// console.log(girl.#weight);//报错
girl.intro(); //调取闭包
二、Promise.allSettled
接收一个Promise的数组,返回一个Promise的对象,返回的结果一定是Promisee的成功的状态,返回的值是Promise的状态和结果
//声明两个promise对象
const p1 = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('商品数据 - 1');
},1000)
});
const p2 = new Promise((resolve, reject)=>{
setTimeout(()=>{
// resolve('商品数据 - 2');
reject('出错啦!');
},1000)
});
//调用 allsettled 方法
const result = Promise.allSettled([p1, p2]);
console.log(result); //返回Promise成功的结果
const res = Promise.all([p1, p2]);
console.log(res); //根据有情况返回Promise成功或失败的结果
三、String.prototype.matchAll
String.prototype.matchAll() 返回一个包含所有匹配正则表达式(或带有全局标志的字符串)的结果的迭代器(iterator)。这个方法比 String.prototype.match() 方法更加强大,因为它可以处理正则表达式中带有全局标志(g)的情况,并返回一个包含所有匹配信息的迭代器,而不仅仅是匹配结果的数组。
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>(.*?)<\/a>.*?<p>(.*?)<\/p>/sg
//调用方法
const result = str.match(reg);
console.log(result);
const resultAll = str.matchAll(reg);
console.log(resultAll);
for(let v of resultAll){
console.log(v);
}
const arr = [...resultAll];
console.log(arr);
四、可选链操作符
1、一般情况下的写法(使用&&不存在值但是不报错)
function main(config){
const dbHost = config && config.db && config.db.host;
console.log(dbHost);
}
2、不使用&&符号会报错
function main(config){
const dbHost = config.db.host;
console.log(dbHost);
}
3、不使用&&符号的时候,怎么保证不报错,运用可选链操作符?.
function main(config){
const dbHost = config?.db?.host;
console.log(dbHost);
}
五、动态 import
<!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="./js/app.js" type="module"></script>
</body>
</html>
export function hello(){
alert('Hello');
}
// import * as m1 from "./hello.js";
//获取元素
const btn = document.getElementById('btn');
btn.onclick = function(){
import('./hello.js').then(module => {
module.hello();
});
}
六、BigInt
更大的数值
//大整形
let a = 521n;
console.log(a, typeof(a));
//函数
let n = 123;
console.log(BigInt(n));
console.log(BigInt(1.2));
//大数值运算
let max = Number.MAX_SAFE_INTEGER;
console.log(max);
console.log(max + 1);
console.log(max + 2);
console.log(BigInt(max))
console.log(BigInt(max) + BigInt(1))
console.log(BigInt(max) + BigInt(2))
七、globalThis
globalThis:全局的this,始终指向全的this
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>globalThis</title>
</head>
<body>
<script>
console.log(globalThis);
</script>
</body>
</html>
console.log(globalThis);