1.运算符
1.指数运算符
指数运算符**,可以计算乘方。2**3等同于Math.pow(2,3)
——来自es7
2.扩展运算符
虽然扩展运算符在es6中就已经存在了,但是只能给函数使用,在es9中为对象也提供了这样的机制。
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, ...obj1 }; // 将obj1的所有属性“剩余”地合并到obj2中
console.log(obj2); // { c: 3, a: 1, b: 2 }
function mergeObjects(base, ...rest) { // base:1 rest:2,3
let result = { ...base }; //a:1
for (const obj of rest) {
result = { ...result, ...obj }; //a:1,b:2 第二轮 a:1,b:2,c:3
}
return result;
}
const baseObj = { a: 1 };
const obj2 = { b: 2 };
const obj3 = { c: 3 };
const mergedObj = mergeObjects(baseObj, obj2, obj3);
console.log(mergedObj); // { a: 1, b: 2, c: 3 }
——es9
3.可选链操作符
可以先判断对象是否有这个属性再使用
const user = {
id: 1,
profile: {
name: "John Doe",
contact: {
email: "john.doe@example.com"
}
}
};
// 传统方式,需要多次检查
let email = user && user.profile && user.profile.contact && user.profile.contact.email;
// 使用可选链操作符
let emailWithOptionalChaining = user?.profile?.contact?.email;
console.log(emailWithOptionalChaining); // 输出: "john.doe@example.com"
// 如果user是undefined
let noUser = undefined;
console.log(noUser?.profile?.contact?.email); // 输出: undefined,而不是抛出错误
4.逻辑赋值操作符
1. 使用逻辑或(||
)进行赋值
逻辑或操作符||
常用于为变量提供一个默认值,如果变量当前为falsey
(如null
、undefined
、0
、""
、NaN
、false
等),则将其设置为默认值。
let a = null;
a = a || 'default value';
console.log(a); // 输出: 'default value'
2. 使用空值合并操作符(??
)进行赋值
空值合并操作符??
用于为null
或undefined
的变量提供一个默认值。这与逻辑或操作符不同,因为它只会在左侧操作数为null
或undefined
时返回右侧的值。
——es12
let b = null;
b = b ?? 'default value'; // 只有当b是null或undefined时,才会被赋值为'default value'
console.log(b); // 输出: 'default value'
let c = 0;
c = c ?? 'default value'; // c不是null或undefined,所以不会被赋值为'default value'
console.log(c); // 输出: 0
5.数字下划线分隔符
let x = 13155557777
let x = 131_5555_7777
两个写法的结果相同,但是用了分隔符以后不用趴在屏幕上一个一个数位数了
——es12
6、Intl.ListFormat
Intl.ListFormat 是一个构造函数,用来处理和多语言相关的对象格式化操作。
const list = ['Apple', 'Orange', 'Banana']
new Intl.ListFormat('en-GB', { style: 'long', type: 'conjunction' }).format(list);
// "Apple, Orange and Banana"
new Intl.ListFormat('zh-cn', { style: 'short', type: 'conjunction' }).format(list);
// 会根据语言来返回相应的格式化操作
// "Apple、Orange和Banana"
——es12
2.对象
1.对象新方法
新增了一些获取对象属性的方法
const person = {
name: 'Alice',
age: 30,
city: 'New York'
};
const keys = Object.keys(person);
console.log(keys); // 输出: ["name", "age", "city"]
const values = Object.values(person);
console.log(values); // 输出: ["Alice", 30, "New York"]
const entries = Object.entries(person);
console.log(entries); // 输出: [["name", "Alice"], ["age", 30], ["city", "New York"]]
for (const [key, value] of entries) {
console.log(`${key}: ${value}`);
// 输出:
// name: Alice
// age: 30
// city: New York
}
注意这些方法不能获取symbol属性,想要获取symbol属性应使用如下方法
const obj = {
prop1: 'value1',
prop2: {
value: 'value2',
writable: false
}
};
const descriptors = Object.getOwnPropertyDescriptors(obj);
//结果如下
{
// prop1: {
// value: 'value1', 属性的值
// writable: true, 可否被修改
// enumerable: true, 可以被遍历(如obj.keys()等)
// configurable: true 描述符可以被改变且该属性可被删除
// },
// prop2: {
// value: { value: 'value2', writable: false },
// writable: true,
// enumerable: true,
// configurable: true
// }
// }
——es8
2.创建新对象
Object.fromEntries方法可以收一个二维数组或map新建对象,和Object.entries()相反
const entries = [
['name', 'John Doe'],
['age', 30],
['isDeveloper', true]
];
const obj = Object.fromEntries(entries);
console.log(obj);
// 输出: { name: 'John Doe', age: 30, isDeveloper: true }
const map = new Map([
['name', 'Jane Doe'],
['age', 28],
['isDeveloper', false]
]);
const obj = Object.fromEntries(map);
console.log(obj);
// 输出: { name: 'Jane Doe', age: 28, isDeveloper: false }
——es10
3.读取Symbol的值
mySymbol.description属性可以读取symbol的值
——es10
4.私有属性
使用#可以定义私有属性了
3.数组
1.查找元素位置
arr.includes()方法可以寻找数组中是否包含某元素
有两个参数,参数一是要寻找的元素,
参数二可选,要寻找的起始位置,负数则为倒数第几个开始,注意只能正序查找
let array = [1, 2, 3];
console.log(array.includes(2)); // true
console.log(array.includes(4)); // false
console.log(array.includes(1, 1)); // false
console.log(array.includes(3, -1)); // true
console.log(array.includes(2, -2)); // true
2.多维数组展开
arr.flat()可以展开数组,参数为展开的层数,默认一层
const arr = [1, 2, 3, 4, [5, [6, 7], 8]];
console.log(arr.flat()); // 输出: [1, 2, 3, 4, 5, [6, 7], 8]
console.log(arr.flat(2)); // 输出: [1, 2, 3, 4, 5, 6, 7, 8]
arr.flatMap()相当于 map([]).flat()
const numbers = [1, 2, 3];
const doubledNumbers = numbers.flatMap(number => [number, number]);
console.log(doubledNumbers); // 输出: [1, 1, 2, 2, 3, 3]
3.at函数
at()函数可以方便快速取出字符串和数组中的指定位置的元素
let arr = ["1","2","3","4"]
console.log(arr[0])
console.log(arr[arr.length-1])
console.log(arr[arr.length-2])
console.log(arr.at(0))
console.log(arr.at(-1)) //最后一个元素
console.log(arr.at(-2)) //倒数第二个元素
let str = "唱跳rap"
console.log(str.at(-1))//最后一个元素
console.log(str.at(-2))//倒数第二个元素
——es13
4.字符串
1.正则扩展
1.命名捕获
const regex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
//(?<year>\d{4}) 组1
//(?<month>\d{2}) 组2
//(?<day>\d{2}) 组3
const match = regex.exec('2023-04-01');
console.log(match.groups.year); // "2023"
console.log(match.groups.month); // "04"
console.log(match.groups.day); // "01"
——es9
2.dotAll模式
该模式下.可以匹配任何换行符,包括但不限于\n, \n\r等
使用此模式的方法就是在正则表达式的末尾加一个s
// 没有使用s标志,.不匹配换行符
const regexNoDotAll = /foo.bar/;
const strWithNewline = "foo\nbar";
console.log(regexNoDotAll.test(strWithNewline)); // false
// 使用s标志,.匹配包括换行符在内的任何字符
const regexDotAll = /foo.bar/s;
console.log(regexDotAll.test(strWithNewline)); // true
——es9
3.新方法
String.prototype.matchAll()返回一个迭代器,返回所有匹配的结果和所在的捕获组,可以使用扩展运算符转换为数组。
RegExp.prototype.flags属性,存储的是正则表达式的模式,一个正则可以有多个模式。
标志字符串中的每个字符都代表一个特定的标志:
g
:全局搜索,即搜索整个字符串中所有匹配的结果,而不是在找到第一个匹配后停止。i
:忽略大小写,即在匹配时不区分大小写。m
:多行搜索,即使^
和$
能够匹配字符串的开始和结束,以及行首和行尾。u
:Unicode 模式,启用对 Unicode 字符集的支持。s
:dotAll 模式,允许.
匹配任何单个字符,包括换行符。y
:粘性(sticky)模式,匹配从目标字符串的当前位置开始。
——es9
2.字符串清除空格
str.trimStart() 清除左侧空白
str.trimEnd() 清除右侧空白
——es10
3.替换字符串
replaceAll()
const str = "qwertyuiop aaaa a aaa qwertyuiop";
const newStr = str.replaceAll('qwertyuiop', "hahaha");
hahaha is a real hahaha
——es12
5.库的导入
const btn = document.getElementById('btn');
btn.onclick = function () {
import('./hello.js').then(module => {
module. Hello();
});
}
——es12
异步
async和await
Promise新操作
Promise.allSettled() 接收一个数组,始终返回一个成功的promise,得到数组中每一个promise成功和失败的状态和结果
Promise.all() 接收一个数组,只有数组中的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);
const res = Promise.all([p1, p2]);
console.log(res);
Promise.any
可以把 Promise.any 理解成 Promise.all 的相反操作。Promise.any 也可以接受一个 Promise 数组,当其中任何一个 Promise 完成(fullfill)时,就返回那个已经有完成值的 Promise。如果所有的 Promise 都拒绝(reject),则返回一个拒绝的 Promise,该 Promise 的返回值是一个 AggregateError 对象。