前言:ES6大家已经在工作中用的炉火纯青了,那么ES6的知识点就不再详细介绍了,一起学习一下ES7 --- ES12 的知识点吧!为了年后的金三银四 冲、冲、冲!!!
目录
5. Object.getOwnPropertyDescriptors()
10.1 我们知道 for...of 是同步运行的,看如下代码
10.2 ES9 中可以用 for...await...of 的语法来操作
11. Promise.prototype.finally()
15. String.prototype.trimStart()
16. Symbol.prototype.description
18. 修订 Function.prototype.toString()
19. 空值合并运算符(Nullish coalescing Operator)
22. String.prototype.matchAll()
26. String.prototype.replaceAll()
一、ES6
① let const : 点此了解详情
② 箭头函数
③ 数组解构赋值
④ 模板字符串
⑤ Generator 和 Iterator :点此了解详情
⑥ promise :点此了解详情
⑦ for..in 和 for...of
ES6 就不过多的详细介绍了,相比大家已经用的很熟练了!!!
二、ES2016(ES7)
1. Array.prototype.includes()
includes( ) 方法用来判断一个数组是否包含一个指定的值,如果包含则返回 true,否则返回 false。
1.2 语法及示例
const arr = ['Barry','Lishen','Jenny','Chany'];
arr.includes(value,index)
value
,需要查找的元素值。index
可选 ,从 index
索引处开始查找 value
。如果为负值,则按升序从 arr.length + index 的索引开始搜索。默认为 0。
const arr = ['Barry', 'Lishen', 'Jenny', 'Chany'];
console.log(arr.includes('Barry')); // true
console.log(arr.includes('Barry',0)); // true
console.log(arr.includes('Barry',1)); // false
console.log(arr.includes('Barry',2)); // false
console.log(arr.includes('Barry',-1)); // false
console.log(arr.includes('Barry',-2)); // false
数组的长度是 4
index 是 -5
computed index 是 4 + (-5) = -1
如果计算出的索引小于 0,则整个数组都会被搜索。 所以下面为 true
console.log(arr.includes('Barry',-5)); // true
计算出的索引小于 0
如果 index 为负值,计算出的索引将作为开始搜索 value 的位置。如果计算出的索引小于 0,则整个数组都会被搜索。
1.3 注意点
① 使用 includes()
查找字符串是区分大小写的。
const arr = ['Barry', 'Lishen', 'Jenny', 'Chany'];
console.log(arr.includes("BARRY")); // fasle
② 使用 includes()
只能判断简单类型的数据,对于复杂类型的数据,比如对象类型的数组,二维数组,这些是无法判断的.
const arr = ['Barry', 'Chany', ['EricNg', 'Tiny'], { name: 'Barry' }];
console.log(arr.includes(['EricNg', 'Tiny'])); // fasle
console.log(arr.includes({ name: 'Barry' })); // fasle
③能识别NaN,indexOf是不能识别NaN的
const arr = ['Barry', 'Lishen', 'Jenny', NaN, 'Chany'];
console.log(arr.includes(NaN)); // true
console.log(arr.indexOf(NaN)); // -1
最后,如果只想知道某个值是否在数组中存在,而并不关心它的索引位置,建议使用includes(),如果想获取一个值在数组中的位置,那么使用indexOf方法。
2. 幂运算符 **
2.1 语法及示例
Math.pow( )
console.log(Math.pow(2, 10)); // 1024
幂运算符 **
console.log(2 ** 4); // 1024
基本求幂
console.log(2 ** 3); // 8
console.log(3 ** 2); // 9
console.log(3 ** 2.5); // 15.588457268119896
console.log(10 ** -1); // 0.1
console.log(NaN ** 4); // NaN
2.2 注意点
幂运算符的两个*号之间不能出现空格,否则语法会报错。
三、ES2017(ES8)
3. Object.values()
Object.values
方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
const obj = {
name: "Barry",
age: 18,
height: 185,
money: 1000000000
}
console.log(Object.values(obj)); // ['Barry', 18, 185, 1000000000]
4. Object.entries()
Object.entries() 方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的键值对数组。
const obj = {
name: "Barry",
age: 18,
height: 185,
money: 1000000000
}
console.log(Object.entries(obj)); // [['name','Barry'], ['age',18], ['height',185], ['money',100000000]]
console.log(Object.entries([1, 2, 3])); // [['0',1], ['1',2], ['2',3]]
5. Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors()
方法用来获取一个对象的所有自身属性的描述符。
const obj = {
name: "Barry",
age: 18,
}
const description = Object.getOwnPropertyDescriptors(obj);
console.log(description)
打印结果
{
age: {
configurable: true
enumerable: true
value: 18
writable: true
}
name: {
configurable: true
enumerable: true
value: "Barry"
writable: true
}
}
上面打印结果中的
-
value
表示当前对象的默认值 -
writable
表示对象属性是否可以修改 -
enumerable
表示当前这个属性是否可以出现在对象的枚举属性中 -
configurable
表示当前对象的属性能否用delete删除
那这些对象的属性我们怎么设置和修改他们呢,我们可以使用 es5 的 Object.defineProperty()
const obj = {
}
Object.defineProperty(obj, 'name', {
value: "Barry",
writable: true,
enumerable: true,
configurable: true
});
Object.defineProperty(obj, 'age', {
value: 18,
writable: true,
enumerable: true,
configurable: true
})
console.log(obj) // {name: 'Barry', age: 18}
接下来我们演示下,一些属性设置为false的情况 :
我们可以看到设置 writable: false和configurable: false,为false时,对象的name对象的值不能改变和不能被删除,打印出来还是原来的对象。
const obj = {
}
Object.defineProperty(obj, 'name', {
value: "Barry",
writable: false,
enumerable: false,
configurable: true
});
console.log(obj) // {name: 'Barry'}
obj.name = 'lishen';
console.log(obj); // {name: 'Barry'}
delete obj.name
console.log(obj); // {name: 'Barry'}
设置enumerable为false时:
当设置enumerable: false时,表示对象的属性不可被枚举,这时打印对象为空,遍历对象的键也为空。
const obj = {
}
Object.defineProperty(obj, 'name', {
value: "Barry",
writable: true,
enumerable: true,
configurable: false
});
console.log(obj) // {}
for (let key in obj) {
console.log(key); // ""
}
6. String.prototype.padStart
6.1 语法
str.padStart(targetLength , padString)
-
targetLength
当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。
-
padString
可选
填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断。此参数的默认值为 " "
6.2 示例
const str = "ABC";
console.log(str.padStart(10)) // " ABC"
console.log(str.padStart(10, 'foo')) // "foofoofABC"
console.log(str.padStart(6, '123456')) // "123ABC"
console.log(str.padStart(8, '0')) // "00000ABC"
console.log(str.padStart(1)) // "ABC"
6.3 应用场景
日期格式化:yyyy-mm-dd的格式:
const now = new Date();
const year = now.getFullYear();
const mounth = (now.getMonth() + 1).toString().padStart(2, '0')
const day = (now.getDate()).toString().padStart(2, '0')
console.log(`${year}-${mounth}-${day}`); // 今天的日期 : 2021-01-27
数字替换(手机号,银行卡号等)
const tel = '18737740333';
function formatTel (tel) {
return tel.slice(-4).padStart(tel.length, '*')
}
console.log(formatTel(tel)); // *******0333
7. String.prototype.padEnd
把指定字符串填充到字符串尾部,返回新字符串。语法同 String.prototype.padStart
const str = "ABC";
console.log(str.padEnd(10)) // "ABC "
console.log(str.padEnd(10, 'foo')) // "ABCfoofoof"
console.log(str.padEnd(6, '123456')) // "ABC123"
console.log(str.padEnd(1)) // "ABC"
8. async/await
我们都知道使用 Promise 能很好地解决回调地狱的问题,但如果处理流程比较复杂的话,那么整段代码将充斥着 then,语义化不明显,代码不能很好地表示执行流程,那有没有比 Promise 更优雅的异步方式呢?那就是async/await!我们一起来揭开它神秘的面纱吧!
8.1 语法
async函数中使用await,那么await这里的代码就会变成同步的了,意思就是说只有等await后面的Promise执行完成得到结果才会继续下去,await就是等待。请看下面的示例:
function timeout () {
return new Promise(resolve => {
setTimeout(() => {
console.log(1);
resolve()
}, 1000);
})
}
// 不加async和await是2、1 加了是1、2
async function foo () {
await timeout()
console.log(2)
}
foo(); // 1, 2
8.2 使用场景
异步处理的逻辑都是使用同步代码的方式来实现的,而且还支持 try catch 来捕获异常,这感觉就在写同步代码,所以是非常符合人的线性思维的。
async function foo () {
try {
let response1 = await fetch('https://www.baidu.com/')
console.log(response1)
let response2 = await fetch('https://juejin.im/')
console.log(response2)
} catch (err) {
console.error(err)
}
}
foo()
8.3 注意点
① await 只能在 async 标记的函数内部使用,单独使用会触发 Syntax error;
② await 后面需要跟异步操作,不然就没有意义了,而且 await 后面的 Promise 对象不必写 then ,因为 await 的作用之一就是获取后面 Promise 对象成功状态传递出来的参数。
8.4 async/await 的缺陷
Async/await
让你的代码看起来是同步的,在某种程度上,也使得它的行为更加地同步。 await
关键字会阻塞其后的代码,直到promise完成,就像执行同步操作一样。它确实可以允许其他任务在此期间继续运行,但您自己的代码被阻塞。
这意味着您的代码可能会因为大量await
的promises相继发生而变慢。每个await
都会等待前一个完成,而你实际想要的是所有的这些promises同时开始处理(就像我们没有使用async/await
时那样)。有一种模式可以缓解这个问题——通过将 Promise
对象存储在变量中来同时开始它们,然后等待它们全部执行完毕。
四、ES2018(ES9)
9. Object Rest & Spread
9.1 语法
这块代码展示了 spread 语法,可以把 input 对象的数据都拓展到 output 对象,这个功能很实用。需要注意的是,如果存在相同的属性名,只有最后一个会生效。
const input = {
a: 1,
b: 2,
c: 3
}
const output = {
...input,
d: 4
}
console.log(output) // {a: 1, b: 2, c: 3, d: 4}
9.2 注意点
如果属性的值是一个对象的话,该对象的引用会被拷贝,而不是生成一个新的对象。
const obj = { x: { y: 10 } };
const copy1 = { ...obj };
const copy2 = { ...obj };
obj.x.y = "jimmy";
console.log(copy1, copy2); // x: {y: "jimmy"} x: {y: "jimmy"}
console.log(copy1.x === copy2.x); // → true
10. for await of
异步迭代器(for-await-of):循环等待每个Promise对象变为resolved状态才进入下一步。
10.1 我们知道 for...of 是同步运行的,看如下代码
function timeout (time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(time)
}, time)
})
}
async function test () {
let arr = [timeout(2000), timeout(1000), timeout(3000),]
for (let item of arr) {
console.log(Date.now(), item.then(console.log))
}
}
test()
10.2 ES9 中可以用 for...await...of 的语法来操作
for await of 环等待每个Promise对象变为resolved状态才进入下一步。所有打印的结果为 2000,1000,3000
function timeout (time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(time)
}, time)
})
}
async function test () {
let arr = [timeout(2000), timeout(1000), timeout(3000),]
for await (let item of arr) {
console.log(Date.now(), item.then(console.log))
}
}
test()
11. Promise.prototype.finally()
Promise.prototype.finally() 方法返回一个Promise,在promise执行结束时,无论结果是fulfilled或者是rejected,在执行then()和catch()后,都会执行finally指定的回调函数。这为指定执行完promise后,无论结果是fulfilled还是rejected都需要执行的代码提供了一种方式,避免同样的语句需要在then()和catch()中各写一次的情况。
11.1 语法
function test () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 1000)
})
}
test().then(res => {
console.log(res);
}).catch(err => {
console.log(err);
}).finally(() => {
console.log('finally');
})
11.2 使用场景
loading关闭
需要每次发送请求,都会有loading提示,请求发送完毕,就需要关闭loading提示框,不然界面就无法被点击。不管请求成功或是失败,这个loading都需要关闭掉,这时把关闭loading的代码写在finally里再合适不过了
五、ES2019(ES10)
12. Object.fromEntries()
方法 Object.fromEntries() 把键值对列表转换为一个对象,这个方法是和 Object.entries() 相对的。
12.1 示例1: Object 转换操作
const obj = {
name: 'jimmy',
age: 18
}
const entries = Object.entries(obj)
console.log(entries)
// [Array(2), Array(2)]
// ES10
const fromEntries = Object.fromEntries(entries)
console.log(fromEntries)
// {name: "jimmy", age: 18}
12.2 示例2: Map 转 Object
const map = new Map();
map.set('name', 'Barry');
map.set('age', 18)
console.log(map); // Map(2) {'name' => 'Barry', 'age' => 18}
const obj = Object.fromEntries(map)
console.log(obj); // {name: 'Barry', age: 18}
12.3 示例3: 过滤
const course = {
math: 80,
english: 85,
chinese: 90
}
const res = Object.entries(course).filter(([key, val]) => val > 80);
console.log(res); // [ [ 'english', 85 ], [ 'chinese', 90 ] ]
console.log(Object.fromEntries(res)); //{english: 85, chinese: 90}
13. Array.prototype.flat()
13.1 语法
let newArray = arr.flat( depth )
depth
可选, 指定要提取嵌套数组的结构深度,默认值为 1。
13.2 Demo
flat()
方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
const arr1 = [0, 1, 2, [3, 4]];
console.log(arr1.flat()); // [0, 1, 2, 3, 4]
const arr2 = [0, 1, 2, [[[3, 4]]]];
console.log(arr2.flat(2)); // [0, 1, 2, [3, 4]]
//使用 Infinity,可展开任意深度的嵌套数组
var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// `flat()` 方法会移除数组中的空项:
var arr5 = [1, 2, , 4, 5];
arr5.flat(); // [1, 2, 4, 5]
14. Array.prototype.flatMap()
flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。从方法的名字上也可以看出来它包含两部分功能一个是 map,一个是 flat(深度为1)。
const numbers = [1, 2, 3]
numbers.map(x => [x * 2]) // [[2], [4], [6]]
numbers.flatMap(x => [x * 2]) // [2, 4, 6]
对比下 map 和 flatMap 的区别
let arr = ['今天天气不错', '', '早上好']
arr.map(s => s.split(''))
// [["今", "天", "天", "气", "不", "错"],[""],["早", "上", "好"]]
arr.flatMap(s => s.split(''))
// ["今", "天", "天", "气", "不", "错", "", "早", "上", "好"]
15. String.prototype.trimStart()
trimStart() 方法从字符串的开头删除空格,trimLeft()是此方法的别名。
String.prototype.trimEnd(), 就不介绍了,和下面类似;
let str = ' foo '
console.log(str.length) // 8
str = str.trimStart() // 或str.trimLeft()
console.log(str.length) // 5
16. Symbol.prototype.description
Symbol 的描述只被存储在内部的 Description
,没有直接对外暴露,我们只有调用 Symbol 的 toString() 时才可以读取这个属性:
const name = Symbol('Barry')
console.log(name); // Symbol(Barry)
console.log(name.toString()); // Symbol(Barry)
console.log(name === 'Symbol(Barry)'); // false
console.log(name.toString() === 'Symbol(Barry)'); // true
现在可以通过 description 方法获取 Symbol 的描述:
const name = Symbol('Barry')
console.log(name.description); // 'Barry'
name.description = "es2" // 只读属性 并不能修改描述符
// 如果没有描述符 输入undefined
const age = Symbol();
console.log(age.description); // undefined
17. JSON.stringify() 增强能力
JSON.stringify 在 ES10 修复了对于一些超出范围的 Unicode 展示错误的问题。因为 JSON 都是被编码成 UTF-8,所以遇到 0xD800–0xDFFF 之内的字符会因为无法编码成 UTF-8 进而导致显示错误。在 ES10 它会用转义字符的方式来处理这部分字符而非编码的方式,这样就会正常显示了。
\uD83D\uDE0E emoji 多字节的一个字符
console.log(JSON.stringify('\uD83D\uDE0E')) // 打印出笑脸
如果我们只去其中的一部分 \uD83D 这其实是个无效的字符串
之前的版本 ,这些字符将替换为特殊字符,而现在将未配对的代理代码点表示为JSON转义序列
console.log(JSON.stringify('\uD83D')) // "\ud83d"
18. 修订 Function.prototype.toString()
以前函数的 toString 方法来自 Object.prototype.toString(), 现在的 Function.prototype.toString() 方法返回一个表示当前函数源代码的字符串。以前只会返回这个函数,不包含注释、空格等。
function foo () {
// ES2019(ES10)
console.log('ES2019(ES10)');
}
console.log(foo.toString());
六、ES2020(ES11)
19. 空值合并运算符(Nullish coalescing Operator)
空值合并操作符( ??
)是一个逻辑操作符,当左侧的操作数为 null
或者undefined
时,返回其右侧操作数,否则返回左侧操作数。
与逻辑或操作符(||
)不同,逻辑或操作符会在左侧操作数为假值时返回右侧操作数。也就是说,如果使用 ||
来为某些变量设置默认值,可能会遇到意料之外的行为。比如为假值(例如''
,0
,NaN
,false
)时。
const name = "" ?? "Barry"
const name2 = "" || "Barry"
console.log(name); // ""
console.log(name2); // "Barry"
const age = 0 ?? 18;
const age2 = 0 || 18;
console.log(age); // 0
console.log(age2); // 18
20. 可选链 Optional chaining
20.1 语法
可选链操作符( ?.
)允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?.
操作符的功能类似于 .
链式操作符,不同之处在于,在引用为 null
或者 undefined
的情况下不会引起错误,该表达式短路返回值是 undefined
。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined
。
当尝试访问可能不存在的对象属性时,可选链操作符将会使表达式更短、更简明。在探索一个对象的内容时,如果不能确定哪些属性必定存在,可选链操作符也是很有帮助的。
const user = {
name: "Barry",
age: 18,
address: {
street: '成华大道',
getNum () {
return '188号'
}
}
}
在之前的语法中,想获取到深层属性或方法,不得不做前置校验,否则很容易命中 Uncaught TypeError: Cannot read property...
这种错误,这极有可能让你整个应用挂掉。
const street = user && user.address && user.address.street
const num = user && user.address && user.address.getNum && user.address.getNum()
console.log(street, num)
使用可选链
const street2 = user?.address?.street
const num2 = user?.address?.getNum?.()
console.log(street2, num2)
20.2 注意点
可选链不能用于赋值
let object = {};
object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment
21. BigInt
BigInt
是一种内置对象,它提供了一种方法来表示大于 2的53次方 \- 1
的整数。这原本是 Javascript 中可以用 Number
表示的最大数字。BigInt
可以表示任意大的整数。
21.1 使用方式一:数字后面增加 n
const bigInt = 9007199254740993n
console.log(bigInt)
console.log(typeof bigInt) // bigint
// `BigInt` 和 [`Number`]不是严格相等的,但是宽松相等的。
console.log(1n == 1) // true
console.log(1n === 1) // false
// `Number` 和 `BigInt` 可以进行比较。
1n < 2 // ↪ true
2n > 1 // ↪ true
21.2 使用方式二:使用 BigInt 函数
const bigIntNum = BigInt(9007199254740993n)
console.log(bigIntNum)
21.3 运算
let number = BigInt(2);
let a = number + 2n; // 4n
let b = number * 10n; // 20n
let c = number - 10n; // -8n
console.log(a);
console.log(b);
console.log(c);
21.4 注意点
BigInt 不能用于 [ Math
] 对象中的方法;不能和任何 [ Number
] 实例混合运算,两者必须转换成同一种类型。在两种类型来回转换时要小心,因为 BigInt
变量在转换成 [ Number
] 变量时可能会丢失精度。
22. String.prototype.matchAll()
matchAll()
方法返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器。
const regexp = /t(e)(st(\d?))/g;
const str = "test1test2"
const arr = [...str.matchAll(regexp)]
console.log(arr);
23. Promise.allSettled()
我们都知道 Promise.all() 具有并发执行异步任务的能力。但它的最大问题就是如果其中某个任务出现异常(reject),所有任务都会挂掉,Promise直接进入reject 状态。
场景:现在页面上有三个请求,分别请求不同的数据,如果一个接口服务异常,整个都是失败的,都无法渲染出数据
我们需要一种机制,如果并发任务中,无论一个任务正常或者异常,都会返回对应的的状态,这就是 Promise.allSettled
的作用
const promise1 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise1')
}, 3000)
})
}
const promise2 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise2')
}, 1000)
})
}
const promise3 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('error promise3')
}, 2000)
})
}
// Promise.all 会走到catch里面
Promise.all([promise1(), promise2(), promise3()]).then(res => {
console.log('all-res', res);
}).catch(err => {
console.log('all-err', err);
})
// Promise.allSettled 不管有没有错误,三个的状态都会返回
Promise.allSettled([promise1(), promise2(), promise3()]).then(res => {
console.log('allSettled-res', res);
}).catch(err => {
console.log('allSettled-err', err);
})
七、ES2021(ES12)
25. 逻辑运算符和赋值表达式(&&=,||=,??=)
25.1 &&=
逻辑与赋值 x &&= y
等效于:
x && (x = y);
上面的意思是,当x为真时,x=y。具体请看下面的示例:
let a = 1;
let b = 0;
a &&= 2;
b &&= 2;
console.log(a); // 2
console.log(b); // 0
25.2 ||=
逻辑或赋值(x ||= y
)运算仅在 x
为 false 时赋值。x ||= y
等同于:x || (x = y);
const a = { duration: 50, title: "" }
a.duration ||= 20;
console.log(a.duration); // 50
a.title ||= "Barry"
console.log(a);
25.3 ??=
逻辑空赋值运算符 ( x ??= y
) 仅在 x
是 nullish[3] ( null
或 undefined
) 时对其赋值。
x ??= y
等价于:x ?? (x = y);
const a = { duration: 50 };
a.duration ??= 10;
console.log(a.duration); // 50
a.speed ??= 25;
console.log(a.speed); // 25
function config(options) {
options.duration ??= 100;
options.speed ??= 25;
return options;
}
config({ duration: 125 }); // { duration: 125, speed: 25 }
config({}); // { duration: 100, speed: 25 }
26. String.prototype.replaceAll()
replaceAll()
方法返回一个新字符串,新字符串中所有满足 pattern
的部分都会被replacement
替换。pattern
可以是一个字符串或一个 RegExp
,replacement
可以是一个字符串或一个在每次匹配被调用的函数。
原始字符串保持不变。
const str = 'aabbccdd';
const newStr = str.replaceAll('b', '*')
console.log(newStr); // 'aa**bbccdd'
使用正则表达式搜索值时,它必须是全局的。
'aabbcc'.replaceAll(/b/, '.');
TypeError: replaceAll must be called with a global RegExp
27. 数字分隔符
欧美语言中,较长的数值允许每三位添加一个分隔符(通常是一个逗号),增加数值的可读性。比如,1000
可以写作1,000
。
ES2021
中允许 JavaScript 的数值使用下划线(_
)作为分隔符。
let budget = 1_000_000_000_000;
budget === 10 ** 12 // true
这个数值分隔符没有指定间隔的位数,也就是说,可以每三位添加一个分隔符,也可以每一位、每两位、每四位添加一个。
123_00 === 12_300 // true
12345_00 === 123_4500 // true
12345_00 === 1_234_500 // true
小数和科学计数法也可以使用数值分隔符。
// 小数
0.000_001
// 科学计数法
1e10_000
数值分隔符有几个使用注意点。
-
不能放在数值的最前面(leading)或最后面(trailing)。
-
不能两个或两个以上的分隔符连在一起。
-
小数点的前后不能有分隔符。
-
科学计数法里面,表示指数的
e
或E
前后不能有分隔符。
下面的写法都会报错。
// 全部报错
3_.141
3._141
1_e12
1e_12
123__456
_1464301
1464301_
28. Promise.any
方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回。
const promise1 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise1')
}, 3000);
})
}
const promise2 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('promise2')
}, 2000);
})
}
const promise3 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('promise3 error')
}, 1000);
})
}
Promise.any([promise1(), promise2(), promise3(),]).then(res => {
// 只要有一个请求成功 就会返回第一个请求成功的
console.log('res', res); // 会返回promise2
}).catch(err => {
console.log('err', err);
})
只要参数实例有一个变成 fulfilled
状态,包装实例就会变成 fulfilled
状态;如果所有参数实例都变成 rejected
状态,包装实例就会变成 rejected
状态。
Promise.any()
跟 Promise.race()
方法很像,只有一点不同,就是 Promise.any()
不会因为某个 Promise 变成 rejected
状态而结束,必须等到所有参数 Promise 变成 rejected
状态才会结束。