ES7
includes
作用
查找一个值是否在指定数组里,在则返回true, 否则返回false
基本用法
['a', 'b', 'c'].includes('a') // true
['a', 'b', 'c'].includes('d') // false
Array.prototype.includes(targetValue, targetIndex)
targetValue: 待搜索的值
targetIndex: 搜索的开始索引
['a', 'b', 'c', 'd'].includes('b') // true
['a', 'b', 'c', 'd'].includes('b', 1) // true
['a', 'b', 'c', 'd'].includes('b', 2) // false
和indexOf的区别
['a', 'b', 'c'].includes('a') //true
['a', 'b', 'c'].indexOf('a') > -1 //true
includes直接返回是否存在的结果,indexOf返回的是参数值的第一个出现位置
对于NaN的判断
let demo = [1, NaN, 2, 3]
demo.indexOf(NaN) //-1
demo.includes(NaN) //true
注意
includes只能判断简单类型的数据,对于对象、对象类型的数组都是无法判断的
指数操作符:(**)
基本用法
let a = 2
a ** 2 // 4
Math.pow(a, 2) // 4
a **= 2 // 4
ES8
Object.values() 和 Object.entries()
let {keys, values, entries} = Object;
let obj = { a: 1, b: 2, c: 3 };
for (let key of keys(obj)) {
console.log(key); // 'a', 'b', 'c'
}
for (let value of values(obj)) {
console.log(value); // 1, 2, 3
}
for (let [key, value] of entries(obj)) {
console.log([key, value]); // ['a', 1], ['b', 2], ['c', 3]
}
Object.values()
定义
返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值
const obj = { foo: 'bar', baz: 42 };
Object.values(obj)
// ["bar", 42]
返回顺序
属性名为数值的属性,是按照数值大小,从小到大遍历的,因此返回的顺序是b、c、a
const obj = { 100: 'a', 2: 'b', 7: 'c' };
Object.values(obj)
// ["b", "c", "a"]
Object.values只返回对象自身的可遍历属性
const obj = Object.create({}, {p: {value: 42}});
Object.values(obj) // []
不显式声明,属性p是不可遍历的
const obj = Object.create({}, {p:
{
value: 42,
enumerable: true
}
});
Object.values(obj) // [42]
Object.values会过滤属性名为 Symbol 值的属性
Object.values({ [Symbol()]: 123, foo: 'abc' });
// ['abc']
Object.values方法的参数是一个字符串
Object.values('foo')
// ['f', 'o', 'o']
Object.values方法的参数是一个数值型或布尔型
Object.values(42) // []
Object.values(true) // []
Object.entries()
定义
Object.entries()方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组
const obj = { foo: 'bar', baz: 42 };
Object.entries(obj)
// [ ["foo", "bar"], ["baz", 42] ]
除了返回值不一样,其他行为和Object.values()基本一致
过滤属性名为 Symbol 值的属性
Object.entries({ [Symbol()]: 123, foo: 'abc' });
// [ [ 'foo', 'abc' ] ]
将对象转为真正的Map结构
const obj = { foo: 'bar', baz: 42 };
const map = new Map(Object.entries(obj));
map // Map { foo: "bar", baz: 42 }
自己实现Object.entries方法
// Generator函数的版本
function* entries(obj) {
for (let key of Object.keys(obj)) {
yield [key, obj[key]];
}
}
// 非Generator函数的版本
function entries(obj) {
let arr = [];
for (let key of Object.keys(obj)) {
arr.push([key, obj[key]]);
}
return arr;
}
padStart(), padEnd(): 字符串补全长度
定义
如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。
'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab'
Async/Await
ES2019
Object.fromEntries()
定义
Object.fromEntries()方法是Object.entries()的逆操作,用于将一个键值对数组转为对象。
Object.fromEntries([ ['foo', 'bar'],
['baz', 42]
])
// { foo: "bar", baz: 42 }
该方法的主要目的,是将键值对的数据结构还原为对象,因此特别适合将 Map 结构转为对象
// 例一
const entries = new Map([
['foo', 'bar'],
['baz', 42]
]);
Object.fromEntries(entries)
// { foo: "bar", baz: 42 }
// 例二
const map = new Map().set('foo', true).set('bar', false);
Object.fromEntries(map)
// { foo: true, bar: false }
是配合URLSearchParams对象,将查询字符串转为对象
Object.fromEntries(new URLSearchParams('foo=bar&baz=qux')) // { foo: "bar", baz: "qux" }
可选的 Catch 绑定
try {
...
} catch (unused) { // 这里的unused可以删除
...
}
JSON超集
在 ES2019 之前,它会产生错误SyntaxError: Invalid or unexpected token
const LS = eval('"\u2028"');
const PS = eval("'\u2029'");
格式良好的JSON.stringfy
// Before
console.log(JSON.stringify("\uD800")); // "�"
// Now ES2019
console.log(JSON.stringify("\uD800")); // "\ud800"
Symbol 符号说明
const mySymbol = Symbol("myDescription");
console.log(mySymbol); // Symbol(myDescription)
console.log(mySymbol.toString()); // Symbol(myDescription)
console.log(mySymbol.description); // myDescription
String.prototype trimStart 和 trimEnd
// Trim
const name = " Codedam ";
console.log(name.trim()); // "Codedam"
// Trim Start
const description = " Unlocks Secret Codes ";
console.log(description.trimStart()); // "Unlocks Secret Codes "
// Trim End
const category = " JavaScript ";
console.log(category.trimEnd()); // " JavaScript"
Array.prototype flat
定义: flat()默认只会“拉平”一层
数组的成员,有时候还是数组,Array.prototype flat 用于将嵌套的数组“拉平”,变成一维数组。
该方法返回一个新数组,对原数据没有影响
[1, 2, [3, 4]].flat()
// [1, 2, 3, 4]
flat的入参是想要“拉平”的层数,默认为1
[1, 2, [3, [4, 5]]].flat()
// [1, 2, 3, [4, 5]]
[1, 2, [3, [4, 5]]].flat(2)
// [1, 2, 3, 4, 5]
如果不管有多少层嵌套,都要转成一维数组,可以用Infinity关键字作为参数。
[1, [2, [3]]].flat(Infinity)
// [1, 2, 3]
如果原数组有空位,flat()方法会跳过空位。
[1, 2, , 4, 5].flat()
// [1, 2, 4, 5]
Array.prototype.flatMap
定义
相当于执行相当于执行Array.prototype.map(),然后对返回值组成的数组执行*flat()*方法
该方法返回一个新数组,不改变原数组。
// 相当于 [[2, 4], [3, 6], [4, 8]].flat()
[2, 3, 4].flatMap((x) => [x, x * 2])
// [2, 4, 3, 6, 4, 8]
flatMap()只能展开一层数组。
// 相当于 [[[2]], [[4]], [[6]], [[8]]].flat()
[1, 2, 3, 4].flatMap(x => [[x * 2]])
// [[2], [4], [6], [8]]
ES2020
可选链操作符:?.
定义
可选链 可让我们在查询具有多个层级的对象时,不再需要进行冗余的各种前置校验。
之前:
if(obj && obj.first && obj.first.second;) {
let nestedProp = obj.first.second
}
现在
let nestedProp = obj?.first?.second;
空位合并操作符: ??
情景:
当给属性设置默认值时,我们经常这样:
let c = a ? a : b // 方式1
let c = a || b // 方式2
这种方式会覆盖所有的假值:0、false、‘’
??在左侧运算符求值为undefined 和null时,返回右侧默认值
let c = a ?? b;
// 等价于let c = a !== undefined && a !== null ? a : b;
Promise.allSettled
应用场景:解决Promise.all中任何一个为reject时,整个Promise.all都会终止的问题
Promise.allSettled([
Promise.reject({ code: 500, msg: '服务异常' }),
Promise.resolve({ code: 200, list: [] }),
Promise.resolve({ code: 200, list: [] })
]).then(res => {
console.log(res)
/*
0: {status: "rejected", reason: {…}}
1: {status: "fulfilled", value: {…}}
2: {status: "fulfilled", value: {…}}
*/
// 过滤掉 rejected 状态,尽可能多的保证页面区域数据渲染
RenderContent(
res.filter(el => {
return el.status !== 'rejected'
})
)
})
String.prototype.matchAll
应用场景
想匹配出所有匹配,需要给正则表达式增加g 或y 修饰符,如果没有*/g*,exec()只返回第一个匹配
可以一次性取出所有匹配,并返回遍历器,可以用for...of取出
function collectGroup1 (regExp, str) {
let results = []
for (const match of str.matchAll(regExp)) {
results.push(match[1])
}
return results
}
console.log(collectGroup1(/"([^"]*)"/g, `"foo" and "bar" and "baz"`))
// ["foo", "bar", "baz"]
BigInt
情景
js只能安全的表示*-(2^53-1)至 2^53-1* 范围内的值,即Number.MIN_SAFE_INTEGER 至Number.MAX_SAFE_INTEGER, 超过这个范围就会丢失精度
var num = Number.MAX_SAFE_INTEGER; // -> 9007199254740991
num = num + 1; // -> 9007199254740992
// 再次加 +1 后无法正常运算
num = num + 1; // -> 9007199254740992
// 两个不同的值,却返回了true
9007199254740992 === 9007199254740993 // -> true
它是第7个原始类型,可安全地进行大数整型计算
你可以在BigInt上使用与普通数字相同的运算符,例如 +, -, /, *, %等等。
创建 BigInt 类型的值也非常简单,只需要在数字后面加上 n 即可
const aNumber = 111;
const aBigInt = BigInt(aNumber);
aBigInt === 111n // true
typeof aBigInt === 'bigint' // true
typeof 111 // "number"
typeof 111n // "bigint"
不能将 BigInt与Number混合使用,比较是可以的,但是不能相加
1n < 2
// true
1n + 2
// Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions
globalThis
globalThis 目的就是提供一种标准化方式访问全局对象,有了 globalThis 后,你可以在任意上下文,任意时刻都能获取到全局对象
之前的开发者通过如下的方法获取全局变量:
- 全局变量 window:是一个经典的获取全局对象的方法。但是它在 Node.js 和 Web Workers 中并不能使用
- 全局变量 self:通常只在 Web Workers 和浏览器中生效。但是它不支持 Node.js。一些人会通过判断 self 是否存在识别代码是否运行在 Web Workers 和浏览器中
- 全局变量 global:只在 Node.js 中生效
// worker.js
globalThis === self
// node.js
globalThis === global
// browser.js
globalThis === window
Object.prototype 必须在全局对象的原型链中
Object.prototype.isPrototypeOf(globalThis); // true
参考链接
- 【JavaScript ES2019 中的 8 个新特性】:juejin.cn/post/684490…
- 【ES2020新特性】:juejin.cn/post/684490…