摘要:
前端开发的都知道,JavaScript经历了不同标本的迭代,从1到12的不断完善中会添加不同的新特性来解决前一个阶段的瑕疵,让我们开发更加便捷与写法更加简洁!
我记得我第一次接触js的时候是从大学的《21天精通JavaScript》,名字很好听,但是现在还在学,还没有精通!哈哈哈哈!
下面来回顾ES5与谈谈ES6、ES7、ES8、ES9、ES10、ES11、ES12都增加了哪些新特性?
回顾ES5的特性:
"use strict" 指令: 定义 JavaScript 代码应该以"严格模式"执行。
String.trim() 删除字符串两端的空白字符。
bash
var str = " Hello World!"
//Hello World!
Array.isArray() 方法检查对象是否为数组。
bash
function myFunction() {
var num= ["1", "2", "3", "4"];
var x = document.getElementById("demo");
x.innerHTML = Array.isArray(num);
}
//true
Array.forEach() 方法为每个数组元素调用一次函数。
bash
var txt = "输出:";
var numbers = [1, 2, 3, 4, 5];
numbers.forEach(myFunction);
function myFunction(value) {
txt = txt + value + "<br>";
}
//输出:1
//输出:2
//输出:3
//输出:4
//输出:5
Array.map() 遍历每个数组值乘以 2
bash
var numbers1 = [1, 2, 3, 4, 5];
var numbers2 = numbers1.map(myFunction);
function myFunction(value) {
return value * 2;
}
//2
//4
//3
//8
//10
Array.filter() 过滤符合值大于 18 的元素创建一个新数组:
bash
var numbers = [45, 4, 9, 16, 25];
var over18 = numbers.filter(myFunction);
function myFunction(value) {
return value > 18;
}
//[45,25]
Array.reduce()与Array.reduceRight() 确定数组中所有数的总和
bash
var numbers1 = [45, 4, 9, 16, 25];
var sum = numbers1.reduce(myFunction);
var sum1 = numbers1.reduceRight(myFunction);
function myFunction(total, value) {
return total + value;
}
//99
Array.every() 检查是否所有值都超过 18
bash
var numbers = [45, 4, 9, 16, 25];
var allOver18 = numbers.every(myFunction);
function myFunction(value) {
return value > 18;
}
//false
Array.some() 检查某些值是否超过 18
bash
var numbers = [45, 4, 9, 16, 25];
var allOver18 = numbers.some(myFunction);
function myFunction(value) {
return value > 18;
}
//true
Array.indexOf() 检索数组中的某个元素值并返回其位置
bash
var fruits = ["Banana", "Orange", "Apple", "Mango"];
var a = fruits.indexOf("Mango");
//3
Array.lastIndexOf() 从数组结尾处开始检索并返回其位置
bash
var fruits = ["Banana", "Orange", "Apple", "Mango"];
var a = fruits.lastIndexOf("Banana");
//0
JSON.parse() 将文本转换为 JavaScript 对象,解析后端返回的数据的时候经常用到
bash
var txt = '{"name":"haha", "age":12, "city":"guangzhou"}'
var obj = JSON.parse(txt);
JSON.stringify() 转换为字符串,传参以及存储对象的时候用到!
bash
var obj = {"name":"haha", "age":12, "city":"guangzhou"};
var myJSON = JSON.stringify(obj);
Date.now() 返回自零日期(1970 年 1 月 1 日 00:00:00:00)以来的毫秒数。
bash
var timInMSs = Date.now();
Object.defineProperty() 定义对象属性和/或更改属性的值和/或元数据
bash
// 创建对象:
var person = {
firstName: "Bill",
lastName : "Gates",
language : "NO",
};
// 更改属性:
Object.defineProperty(person, "language", {
value: "EN",
writable : true,
enumerable : true,
configurable : true
});
// 枚举属性
var txt = "";
for (var x in person) {
txt += person[x] + "<br>";
}
Object.defineProperty(object, property, descriptor) 添加或更改对象属性
Object.defineProperties(object, descriptors) 添加或更改多个对象属性
Object.getOwnPropertyDescriptor(object, property) 访问属性
Object.getOwnPropertyNames(object) 将所有属性作为数组返回
Object.keys(object) 将可枚举属性作为数组返回
Object.getPrototypeOf(object) 访问原型
Object.preventExtensions(object) 防止向对象添加属性
Object.isExtensible(object) 如果可以将属性添加到对象,则返回 true
Object.seal(object) 防止更改对象属性(而不是值)
Object.isSealed(object) 如果对象被密封,则返回 true
Object.freeze(object) 防止对对象进行任何更改
Object.isFrozen(object) 如果对象被冻结,则返回 true
charAt() 方法返回字符串中指定索引(位置)的字符:
bash
var str = "HELLO WORLD";
str.charAt(0);
//str[0];
// 返回 H
...
ES6增加新特性
ES6 全套教程 ECMAScript6 (原著:阮一峰)
let 和 const 声明变量
ES6 引入了两种新的声明变量的方式:let 和 const。let 声明的变量具有块级作用域,可以避免变量提升问题,而 const 声明的变量则是常量,一旦被赋值就不能被修改。
模板字符串(Template Literals)
模板字符串是一种新的字符串语法,可以使用反引号 `` 来定义字符串,同时可以在字符串中插入变量或表达式,使用 ${} 来表示。
解构赋值(Destructuring)
解构赋值是一种快速访问和赋值一个数组或对象的方式。可以通过解构赋值来快速获取数组或对象中的值,同时也可以用来交换变量的值。
箭头函数(Arrow Functions)
箭头函数是一种更简洁的函数定义方式,可以使用 => 来定义函数。它的特点是没有自己的 this,this 的指向由外层作用域决定。
Promise 对象
Promise 是一种更优雅的异步编程解决方案,可以避免回调地狱问题。它是一个对象,代表一个异步操作的最终完成或失败状态,可以在异步操作完成后执行一些处理逻辑。
函数参数默认值
ES6 允许在函数定义时为参数设置默认值,当函数调用时没有传入对应参数的值时,参数就会使用默认值。
对象字面量增强(Object Literal Enhancements)
对象字面量增强是一种更简洁的定义对象的方式,可以使用简洁的语法来定义对象的属性和方法。例如可以使用变量来作为对象属性的名称,同时也可以使用箭头函数来定义对象的方法。
类和继承(Classes and Inheritance)
ES6 引入了类和继承的概念,可以通过 class 关键字来定义类,并使用 extends 来实现继承。
迭代器(Iterators)
迭代器是一种新的遍历方式,可以自定义遍历对象的方式。通过实现一个 next() 方法,可以控制对象的遍历过程。
生成器(Generators)
生成器是一种可以暂停和恢复执行的函数,可以通过 yield 关键字来实现暂停和恢复。生成器可以用来简化异步编程的逻辑。
模块(Modules)
ES6 引入了 import 和 export 关键字,用来定义模块的导入和导出。模块可以帮助我们更好地组织代码,避免命名冲突和代码重复。
Set 和 Map 数据结构
Set 和 Map 是两种新的数据结构,可以用来存储唯一的值和键值对。Set 是一组唯一的值的集合,Map 是一组键值对的集合。
Symbol 数据类型
Symbol 是一种新的原始数据类型,可以用来定义唯一的属性名。
for...of 循环
for...of 循环是一种新的遍历方式,可以遍历具有迭代器的数据结构。
let 和 const 块级作用域
let 和 const 声明的变量具有块级作用域,可以避免变量提升问题,同时也可以避免命名冲突和变量覆盖的问题。
异步函数 async/await
异步函数是一种更加优雅的异步编程解决方案,可以使用 async 和 await 关键字来定义和调用异步函数。
ES7
Array.prototype.includes
Exponentiation Operator
Array.prototype.includes 判断一个数组或字符串中是否包含一个指定的值,如果包含返回true ,否则返回false
bash
arr.includes(valueToFind)
arr.includes(valueToFind, fromIndex)
let arr = [1, 2, 3, 4];
arr.includes(3); // true
arr.includes(5); // false
arr.includes(3, 1); // true
//fromIndex大于等于数组长度
arr.includes(3, 3); // false
arr.includes(3, 20); // false
计算出的索引小于0:
如果fromIndex为负值,使用数组长度 + fromIndex计算出的索引作为新的fromIndex,如果新的fromIndex为负值,则搜索整个数组。
bash
arr.includes(3, -100); // true
arr.includes(3, -1); // false
Exponentiation Operator幂运算: 相当于Math.pow()
bash
5 ** 2 // 25
Math.pow(5, 2) // 25
ES8
Async functions
Object.entries
Object.values
Object.getOwnPropertyDescriptors
Trailing commas
1、Async functions 是 async 声明的函数,async 函数是 AsyncFunction 构造函数的实例,其中允许使用 await 关键字。
bash
async function name([param[, param[, ...param]]]) {
// statements
}
//返回一个Promise
const promise = () => {
console.log('1');
return new Promise((resolve, reject) => {
resolve('2');
});
};
const asyncFun = async() => {
console.log('3');
const test = await promise();
console.log('4', test);
}
asyncFun(); // 3 1 4 2
2、Object.entries
bash
Object.entries(obj);
//返回一个给定对象自身可枚举属性的键值对数组
let obj = {a: 1, b: 2};
Object.entries(obj); // [['a', 1], ['b', 2]]
3、Object.values
bash
Object.values(obj);
//返回一个给定对象自身可枚举属性值的数组
let obj = {a: 1, b: 2};
Object.values(obj); // [1, 2]
4、Object.getOwnPropertyDescriptors
bash
Object.getOwnPropertyDescriptors(obj);
//获取一个对象的所有自身属性的描述符
let obj = {a: 1, b: 2};
Object.getOwnPropertyDescriptors(obj);
// [a: {configurable: true, enumerable: true, value: 1, writable: true}, b: {configurable: true, enumerable: true, value: 2, writable: true}]
5、Trailing commas 尾后逗号
如果你想要添加新的属性,并且在上一行已经使用了尾后逗号,你可以仅仅添加新的一行,而不需要修改上一行
注意:JSON 不允许尾后逗号
bash
//字面量中的尾后逗号
let obj = {
a: 1,
b: 2
}
let arr = [
1,
2
]
//函数中的尾后逗号
function(x, y) {}
function(x, y,) {}
(x, y) => {}
(x, y,) => {}
fun(x, y)
fun(x, y,)
//解构中的尾后逗号
let [a, b,] = [1, 2];
let {x, y} = {x: 1, y: 2};
//JSON中不允许出现尾后逗号
JSON.parse("[1, 2, 3,]") // ❌
JSON.parse('{"a": 1,}') // ❌
JSON.parse("[1, 2, 3]") // ✅
JSON.parse('{"a": 1}') // ✅
6、String.prototype.padStart() 用另一个字符串填充当前字符串
在原字符串开头填充指定的填充字符串直到目标长度所形成的新字符串
bash
str.padStart(targetLength);
str.padStart(targetLength, padString);
//targetLength:当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。
//padString(可选):填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断。此参数的默认值为 " "
abc'.padStart(10); // " abc"
'abc'.padStart(10, "foo"); // "foofoofabc"
'abc'.padStart(6,"123465"); // "123abc"
'abc'.padStart(8, "0"); // "00000abc"
'abc'.padStart(1); // "abc"
7、String.prototype.padEnd() 用一个字符串填充当前字符串(如果需要的话则重复填充)
返回在原字符串末尾填充指定的填充字符串直到目标长度所形成的新字符串
bash
str.padEnd(targetLength)
str.padEnd(targetLength, padString)
//targetLength:当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。
//padString(可选):填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断。此参数的缺省值为 " "。
'abc'.padEnd(10); // "abc "
'abc'.padEnd(10, "foo"); // "abcfoofoof"
'abc'.padEnd(6, "123456"); // "abc123"
'abc'.padEnd(1); // "abc"
ES9
Async iterators 异步迭代器
Object rest properties 剩余属性
Object spread properties 扩展属性
Promise.prototype.finally
Async iterators 异步迭代器
Async iterator 对象的 next() 方法返回一个 Promise,这个 Promise 的返回值可以被解析成 {value, done} 的格式,
bash
iterator.next().then(({value, done}) => {});
bash
const asyncIterator = () => {
const array = [1, 2];
return {
next: function() {
if(array.length) {
return Promise.resolve({
value: array.shift(),
done: false
});
}
return Promise.resolve({
done: true
});
}
}
}
let iterator = asyncIterator();
const test = async() => {
await iterator.next().then(console.log); // {value: 1, done: false}
await iterator.next().then(console.log); // {value: 2, done: false}
await iterator.next().then(console.log); // {done: true}
}
test();
可以使用 for-await-of 在循环中异步调用函数
bash
const promises = [
new Promise((resolve) => resolve(1)),
new Promise((resolve) => resolve(2)),
new Promise((resolve) => resolve(3)),
];
const test = async() => {
for await (const p of promises) {
console.log('p', p);
}
};
test();
Object rest properties
bash
let test = {
a: 1,
b: 2,
c: 3,
d: 4
}
let {a, b, ...rest} = test;
console.log(a); // 1
console.log(b); // 2
console.log(rest); // {c: 3, d: 4}
bash
//null 不能使用扩展运算符
let {a, b, ...rest} = null; // ❌
Object spread properties
bash
let test = {
a: 1,
b: 2
}
let result = {c: 3, ...test};
console.log(result); // {c: 3, a: 1, b: 2}
bash
let test = null;
let result = {c: 3, ...test}; // {c: 3}
Promise.prototype.finally
在Promise结束的时候,不管是结果是resolved还是rejected,都会调用finally中的方法
finally中的回调函数不接受任何参数
bash
//返回一个Promise
const promise = new Promise((resolve, reject) => {
resolve('resolved');
reject('rejectd');
})
promise.then((res) => {
console.log(res);
}).finally(() => {
console.log('finally')
});
const promise = new Promise((resolve, reject) => {
resolve(1);
reject(2);
});
const test = () => {
console.log(3);
promise.then((res) => {
console.log(4, res);
}).catch(err => {
console.log(5, err);
}).finally(() => {
console.log(6);
});
};
test(); // 3 4 1 6
ES10
Array.prototype.{flat, flatMap}扁平化嵌套数组
Object.fromEntries
String.prototype.{trimStart, trimEnd}
Symbol.prototype.description
Optional catch binding
Array.prototype.sort() is now required to be stable
Array.prototype.{flat, flatMap} 扁平化嵌套数组
1、Array.prototype.flat
flat()方法会按照一个可指定的深度遍历递归数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
bash
//depth 是数组遍历的深度,默认是1。
arr.flat([depth]);
1-2、返回一个新数组,不会改变旧数组。
bash
const arr = [1, 2, [[[[3, 4]]]]];
arr.flat(); // [1, 2, [[[3, 4]]]]
arr.flat(3); // [1, 2, [3, 4]]
arr.flat(-1); // [1, 2, [[[[3, 4]]]]]
arr.flat(Infinity); // [1, 2, 3, 4]
1-3、flat()会移除数组中的空项
bash
let arr = [1, 2, , , 3];
arr.flat(); // [1, 2, 3]
1-4、替换
bash
//reduce与concat
let arr = [1, 2, [3, 4]];
arr.reduce((arr, val) => arr.concat(val), []);
//... 扩展运算符与concat
let arr = [1, 2, [3, 4]];
[].concat(...arr);
2、Array.prototype.flatMap
flatMap()方法首先使用映射函数映射数组(深度值为1)的每个元素,然后将结果压缩成一个新数组。
2-1、返回一个新数组,并且每个元素都是回调函数的结果。
bash
arr.flatMap(function callback(currentVal[, index[, array]]) {}[, thisArg])
callback: 可以生成一个新数组所调用的函数
currentVal: 当前数组在处理的元素
index: 可选,正在处理的元素索引
array: 可选,被调用的数组
thisArg: 执行callback函数时使用的this值
let arr = ['My name', 'is', '', 'Lisa'];
let newArr1 = arr.flatMap(cur => cur.split(' '));
let newArr2 = arr.map(cur => cur.split(' '));
console.log(newArr1); // ["My", "name", "is", "", "Lisa"]
console.log(newArr2); // [["My", "name"], ["is"], [""], ["Lisa"]]
3、Object.fromEntries
fromEntries() 方法会把键值对列表转换成一个对象
返回一个新的对象
bash
Object.fromEntries(iterable)
//iterable: Array、Map等可迭代对象
bash
let map = new Map([['a', 1], ['b', 2]]);
let mapToObj = Object.fromEntries(map);
console.log(mapToObj); // {a: 1, b: 2}
let arr = [['a', 1], ['b', 2]];
let arrToObj = Object.fromEntries(arr);
console.log(arrToObj); // {a: 1, b: 2}
let obj = {a: 1, b: 2};
let newObj = Object.fromEntries(
Object.entries(obj).map(
([key, val]) => [key, val * 2]
)
);
console.log(newObj); // {a: 2, b: 4}
4、String.prototype.{trimStart, trimEnd}
4-1、String.prototype.trimStart
trimStart() 方法用来删除字符串的开头的空白字符。
trimLeft() 是它的别名。
4-1-4、返回一个新的字符串,这个字符串左边的空格已经被去除掉了。
bash
str.trimStart();
str.trimLeft();
bash
let str = ' a b cd ';
str.trimStart(); // 'a b cd '
str.trimLeft(); // 'a b cd '
4-2、String.prototype.trimEnd
trimEnd() 方法用来删除字符串末尾的空白字符。
trimRight() 是它的别名
4-2-1、返回一个新的字符串,这个字符串右边的空格已经被去除了
bash
str.trimEnd()
str.trimRight()
bash
let str = ' a b cd ';
str.trimEnd(); // ' a b cd'
str.trimRight();
5、Symbol.prototype.description
description 是一个只读属性
5-1、返回它返回Symbol对象的可选描述的字符串
bash
Symbol('myDescription').description;
Symbol.iterator.description;
Symbol.for('foo').description;
bash
Symbol('foo').description; // 'foo'
Symbol().description; // undefined
Symbol.for('foo').description; // 'foo'
6、Optional catch binding
可选的捕获绑定,允许省略catch绑定和它后面的圆括号
bash
//以前的用法:
try {
} catch(err) {
console.log('err', err);
}
//ES10 的用法:
try {
} catch {
}
7、JSON.stringify() 的增强力
SON.stringify() 在 ES10 修复了对于一些超出范围的 Unicode 展示错误的问题,所以遇到 0xD800-0xDFF 之内的字符会因为无法编码成 UTF-8 进而导致显示错误。在 ES10 它会用转义字符的方式来处理这部分字符而非编码的方式,这样就会正常显示了。
bash
JSON.stringify('😊'); // '"😊"'
8、修订Function.prototype.toString()
以前的 toString 方法来自 Object.prototype.toString(),现在 的 Function.prototype.toString() 方法返回一个表示当前函数源代码的字符串。以前只会返回这个函数,不会包含空格、注释等。
bash
function foo() {
// es10新特性
console.log('imooc')
}
console.log(foo.toString());
// function foo() {
// // es10新特性
// console.log('imooc')
// }
ES11
空值合并运算符(Nullish coalescing Operator)
可选链 Optional chaining
globalThis
BigInt
String.prototype.matchAll()
Promise.allSettled()
Dynamic import(按需 import)
1、空值合并运算符(Nullish coalescing Operator)
1-1 空值合并操作符(??)
空值合并操作符(??)是一个逻辑操作符,当左边的操作数为 null 或 undefined 的时候,返回其右侧操作符,否则返回左侧操作符。
bash
undefined ?? 'foo' // 'foo'
null ?? 'foo' // 'foo'
'foo' ?? 'bar' // 'foo'
1-2 逻辑或操作符(||)
逻辑或操作符(||),会在左侧操作数为假值时返回右侧操作数,也就是说如果使用 || 来为某些变量设置默认值,可能会出现意料之外的情况。比如 0、''、NaN、false:
bash
0 || 1 // 1
0 ?? 1 // 0
'' || 'bar' // 'bar'
'' ?? 'bar' // ''
NaN || 1 // 1
NaN ?? 1 // NaN
false || 'bar' // 'bar'
false ?? 'bar' // false
1-3 注意
不可以将 ?? 与 AND(&&)OR(||)一起使用,会报错。
bash
null || undefined ?? "foo"; // 抛出 SyntaxError
true || undefined ?? "foo"; // 抛出 SyntaxError
2、可选链 Optional chaining
可选链操作符(?.)允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用都是否有效。?. 操作符的功能类似于.链式操作符,不同之处在于,在引用为 null 或 undefined 时不会报错,该链路表达式返回值为 undefined。
bash
//以前的写法
const street = user && user.address && user.address.street;
const num = user && user.address && user.address.getNum && user.address.getNum();
console.log(street, num);
//ES11 的写法:
const street2 = user?.address?.street;
const num2 = user?.address?.getNum?.();
console.log(street2, num2);
-.2 注意
可选链不能用于赋值:
bash
let object = {};
object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment
3、globalThis
以前,在 Web 中,可以通过 window、self 取到全局对象,在 node.js 中,必须使用 global。
在松散模式下,可以在函数中返回 this 来获取全局对象,但是在严格模式和模块环境下,this 会返回 undefined。
以前要获取全局对象,可以定义一个函数:
bash
const getGlobal = () => {
if (typeof self !== 'undefined') {
return self
}
if (typeof window !== 'undefined') {
return window
}
if (typeof global !== 'undefined') {
return global
}
throw new Error('无法找到全局对象')
}
const globals = getGlobal()
console.log(globals)
现在 globalThis 提供了一个标准的方式来获取不同环境下的全局对象自身值。
4、BigInt
BigInt 是一种内置对象,用来创建比 2^53 - 1(Number 可创建的最大数字) 更大的整数。可以用来表示任意大的整数
4-1、如何定义一个 BigInt
在一个整数字面量后面加 n,例如 10n
调用函数 BigInt() 并传递一个整数值或字符串值,例如 BigInt(10)
4-2 、BigInt 的特点
BigInt 不能用于 Math 对象中的方法;
BigInt 不能与任何 Number 实例混合运算,两者必须转换成同一种类型。但是需要注意,BigInt 在转换成 Number 时可能会丢失精度。
当使用 BigInt 时,带小数的运算会被向下取整
BigInt 和 Number 不是严格相等,但是宽松相等
bash
0n === 0 // false
0n == 0 // true
BigInt 和 Number 可以比较
bash
2n > 2 // false
2n > 1 // true
BigInt 和 Number 可以混在一个数组中排序
bash
const mixed = [4n, 6, -12n, 10, 4, 0, 0n];
mixed.sort(); // [-12n, 0, 0n, 10, 4n, 4, 6]
被 Object 包装的 BigInt 使用 object 的比较规则进行比较,只用同一个对象比较时才相等
bash
0n === Object(0n); // false
Object(0n) === Object(0n); // false
const o = Object(0n);
o === o // true
4.3 BigInt 的方法
4.3.1 BigInt.asIntN()
将 BigInt 值转换为一个 -2^(width-1) 与 2^(width-1) - 1 之间的有符号整数。
4.3.2 BigInt.asUintN()
将一个 BigInt 值转换为 0 与 2^(width) - 1 之间的无符号整数。
4.3.3 BigInt.prototype.toLocaleString()
返回此数字的 language-sensitive 形式的字符串。覆盖 Object.prototype.toLocaleString() 方法。
4.3.4 BigInt.prototype.toString()
返回以指定基数 (base) 表示指定数字的字符串。覆盖 Object.prototype.toString() 方法。
4.3.5 BigInt.prototype.valueOf()
返回指定对象的基元值。覆盖 Object.prototype.valueOf() 方法。
5、String.prototype.matchAll()
返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器
bash
const regexp = /t(e)(st(d?))/g;
const str = 'test1test2';
const array = [...str.matchAll(regexp)];
console.log(array[0]); // ["test1", "e", "st1", "1"]
console.log(array[1]); // ["test2", "e", "st2", "2"]
6、Promise.allSettled()
类方法,返回一个在所有给定的 promise 都已经 fulfilled 或 rejected 后的 promise,并带有一个对象数组,每个对象表示对应的 promise 结果。
bash
Promise.allSettled([
Promise.resolve(33),
new Promise((resolve) => setTimeout(() => resolve(66), 0)),
99,
Promise.reject(new Error("an error")),
]).then((values) => console.log(values));
// [
// { status: 'fulfilled', value: 33 },
// { status: 'fulfilled', value: 66 },
// { status: 'fulfilled', value: 99 },
// { status: 'rejected', reason: Error: an error }
// ]
7、Dynamic import(按需 import)
import 可以在需要的时候,再加载某个模块。
bash
button.addEventListener('click', event => {
import('./dialogBox.js')
.then(dialogBox => {
dialogBox.open();
})
.catch(error => {
/* Error handling */
})
});
ES12
逻辑运算符和赋值表达式(&&=,||=,??=)
String.prototype.replaceAll()
数字分隔符
Promise.any
一、逻辑运算符和赋值表达式(&&=,||=,??=)
1.1 &&=
逻辑与赋值运算符 x &&= y 等价于 x && (x=y):意思是当 x 为真时,x = y。
bash
let a = 1;
let b = 0;
a &&= 2;
console.log(a); // 2
b &&= 2;
console.log(b); // 0
1.2 ||=
逻辑或赋值运算符 x ||= y 等价于 x || (x = y):意思是仅在 x 为 false 的时候,x = y。
bash
const a = { duration: 50, title: '' };
a.duration ||= 10;
console.log(a.duration); // 50
a.title ||= 'title is empty.';
console.log(a.title); // "title is empty"
1.3 ??=
逻辑空赋值运算符 x ??= y 等价于 x ?? (x = y):意思是仅在 x 为 null 或 undefined 的时候,x = y。
bash
const a = { duration: 50 };
a.duration ??= 10;
console.log(a.duration); // 50
a.speed ??= 25;
console.log(a.speed); // 25
二、String.prototype.replaceAll()
返回一个新字符串,字符串中所有满足 pattern 的部分都会被 replacement 替换掉。原字符串保持不变。
pattern 可以是一个字符串或 RegExp;
replacement 可以是一个字符串或一个在每次被匹配被调用的函数。
bash
'aabbcc'.replaceAll('b', '.'); // 'aa..cc'
使用正则表达式搜索值时,必须是全局的:
bash
'aabbcc'.replaceAll(/b/, '.'); // TypeError: replaceAll must be called with a global RegExp
'aabbcc'.replaceAll(/b/g, '.'); // "aa..cc"
三、数字分隔符
ES12 允许 JavaScript 的数值使用下划线(_)作为分隔符,但是没有规定间隔的位数:
bash
123_00
小数和科学记数法也可以使用分隔符:
bash
0.1_23
1e10_00
注意:
不能放在数值的最前面和最后面;
不能将两个及两个以上的分隔符连在一起;
小数点的前后不能有分隔符;
科学记数法里,e 或 E 前后不能有分隔符。
四、Promise.any
方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回。
只要参数实例有一个变成 fulfilled 状态,包装实例就会变成 fulfilled 状态;如果所有参数实例都变成 rejected 状态,包装实例就会变成 rejected 状态。
bash
const promise1 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("promise1");
// reject("error promise1 ");
}, 3000);
});
};
const promise2 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("promise2");
// reject("error promise2 ");
}, 1000);
});
};
const promise3 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("promise3");
// reject("error promise3 ");
}, 2000);
});
};
Promise.any([promise1(), promise2(), promise3()])
.then((first) => {
// 只要有一个请求成功 就会返回第一个请求成功的
console.log(first); // 会返回promise2
})
.catch((error) => {
// 所有三个全部请求失败 才会来到这里
console.log("error", error);
});
bash
Promise.any([promise1(), promise2(), promise3()])
.then((first) => {
// 只要有一个请求成功 就会返回第一个请求成功的
console.log(first); // 会返回promise2
})
.catch((error) => {
// 所有三个全部请求失败 才会来到这里
console.log("error", error);
});