ES6及以上语法汇总

219 阅读7分钟

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、‘’

??在左侧运算符求值为undefinednull时,返回右侧默认值

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

应用场景

想匹配出所有匹配,需要给正则表达式增加gy 修饰符,如果没有*/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_INTEGERNumber.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

参考链接