ES7-ES11新特性汇总

ES7-ES11新特性

在这里插入图片描述

ES7新特性归纳(2016)

1、Array.prototype.includes()

判断一个数组是否包含一个元素
会首先想到indexOf(),这个方法会返回当前数组元素的下标:

const arr = ["es6", "es7", "es8", "es9", "es10", "es11"]
console.log(arr.indexOf("es6"))   // 0
console.log(arr.indexOf("es12"))  // -1
const arr = ["es6", "es7", "es8", "es9", "es10", "es11", NaN]
console.log(arr.indexOf(NaN))  // -1

indexOf()无法判断数组中是否含有NaN,由此,es7提供给数组一个新的API——Array.prototype.includes方法,返回一个布尔值,表示某个数组是否包含给定的值。

①基本用法
const arr = ["es6", "es7", "es8", "es9", "es10", "es11"NaN]
console.log(arr.includes("es6"))   // true
console.log(arr.includes(NaN))   // true
console.log(arr.includes("es12"))  // false
[1, 2, 3].includes(3, 3);  // false
[1, 2, 3].includes(3, -1); // true

  • Array.prototype.includes():可以接收两个参数,要搜索的值和搜索的开始索引。第二个参数可选,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。
  • 只能判断简单类型的数据,对于复杂类型的数据,比如对象类型的数组,二维数组,这些是无法判断的。
②区别

都可以用来判断数组中是否包含一个元素,唯一的区别在于includes可以识别NaN。

2、指数运算符

在es5中我们可以通过Math.pow()来实现:

console.log(Math.pow(2,53))

es7提供了一种 ** 运算符,可以更简单实现

console.log(2**53)

注:幂运算符的两个*号之间不能出现空格,前后有无空格都可以。

ES8新特性归纳(2017)

1、async/await

async/await是继es6中promise、generator后又一种更加优雅的异步编程的解决方案
async函数是generator函数的语法糖
在我们处理异步的时候,比起回调函数,Promise的then方法会显得较为简洁和清晰,但是在处理多个彼此之间相互依赖的请求的时候,就会显的有些繁琐。这时候,用async/await更加优雅。
使用 Promise 之后可以让我们书写异步操作更加简单,而 async 是让我们写起 Promise 像同步操作。
async用于声明一个异步的function,await用于等待一个异步方法执行完成。

基本用法

在函数,匿名函数,箭头函数,变量,类中加上关键字async。
前面添加了async的函数在执行后都会自动返回一个Promise对象:

// 不加async
function foo() {
    return 'imooc'
}
console.log(foo()) // 'imooc'

// 加async
async function foo() {
    return 'imooc'
}
console.log(foo()) // Promise.resolve('imooc')

async函数体内可以使用await关键字,且await关键字只能出现在async函数体内,await的作用之一就是获取后面Promise对象成功状态传递出来的参数。

function timeout() {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log(1);
            resolve(); // resolve('success')
        }, 1000)
    })
}

// 不加async和await是2、1   加了是1、2
async function foo() {
    await timeout();
    console.log(2);
}
foo();

2、Object.values()、Object.entries()

获取一个对象的每一个属性值,在es5中常用Object.keys()及for in来直接获取:

// Object,keys()
const obj = {
  name: "张三",
  age: 18,
  sex: "male",
}

const values = Object.keys(obj).map(item => {
  return obj[item]
})
console.log(values)   // ["张三", 18, "male"]

// for in
for (let key in obj) {
  console.log(obj[key])
}
// "张三", 18, "male"

es8为我们扩展了两个新的静态方法:

①Object.values()

Object.values() 返回一个数组,数组元素是在对象上找到的可枚举属性值。

const obj = {
  name: "张三",
  age: 18,
  sex: "male",
}
console.log(Object.values(obj)) // ["张三", 18, "male"]
②Object.entries()

Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组。

const obj = {
  name: "张三",
  age: 18,
  sex: "male",
}
console.log(Object.entries(obj))
// [["name", "张三"],["age", "18"], ["sex", "male"]]
③区别

for in可以遍历出原型链上的可枚举属性,而Object.keys()/Object.values()/Object.entries()只能遍历自身的可枚举属性

const obj = {
  name: "张三",
  age: 18,
  sex: "male",
}
Object.prototype.test = "test"

for (let key in obj) {
  console.log(obj[key])
}
//  "张三", 18, "male","test"
console.log(Object.keys(obj).map(key => obj[key]))
// ["张三", 18, "male"]
console.log(Object.values(obj))
// ["张三", 18, "male"]
console.log(Object.entries(obj).map(([key, value]) => value))
// ["张三", 18, "male"]

3、Object.getOwnPropertyDescriptors()

Object.defineProperty()获取一个对象的所有自身属性的描述符,如果没有任何自身属性,则返回空对象。所谓描述符(顾名思义数据的描述符就是对数据进行描述,会描述出数据是否可以被遍历,被枚举,被赋值等行为):

  1. value [属性的值]
  2. writable [属性的值是否可被改变]
  3. enumerable [属性的值是否可被枚举]
  4. configurable [描述符本身是否可被修改,属性是否可被删除]
let test = {
  name: '测试',
  value: 5
}
console.log(Object.getOwnPropertyDescriptors(test)) 
// {
//   name: {value: "测试", writable: true, enumerable: true, configurable: true}
//   value: {value: 5, writable: true, enumerable: true, configurable: true}
// }

Object.getOwnPropertyDescriptors(target,param)接收两个参数,返回某一个参数的描述符。

const data = {
  PortLand: '78/50',
  DuLin: '88/52',
  Lima: '58/40'
}
// 使指定数据不可枚举
Object.defineProperty(data, 'Lima', {
  enumerable: false
})
console.log(Object.keys(data)) // ["PortLand", "DuLin"]
console.log(Object.getOwnPropertyDescriptor(data, 'Lima')) 
//{value: "58/40", writable: true, enumerable: false, configurable: true}

4、String padding

ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。

'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'

'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'

padStartpadEnd一共接受两个参数,第一个参数用来指定字符串的最小长度,第二个参数是用来补全的字符串。
如果原字符串的长度,等于或大于指定的最小长度,则返回原字符串。

'xxx'.padStart(2, 'ab') // 'xxx'
'xxx'.padEnd(2, 'ab') // 'xxx'

如果用来补全的字符串与原字符串,两者的长度之和超过了指定的最小长度,则会截去超出位数的补全字符串。

'abc'.padStart(10, '0123456789')
// '0123456abc'

如果省略第二个参数,默认使用空格补全长度。

'x'.padStart(4) // '   x'
'x'.padEnd(4) // 'x   '

5、尾逗号

此前,函数定义和调用时,都不允许最后一个参数后面出现逗号,es8 允许函数的最后一个参数有尾逗号。

// es8以前
function foo(a, b, c, d) {
  console.log(a, b, c, d)
}

// es8
function foo(a, b, c, d,) {
  console.log(a, b, c, d)
}

6、SharedArrayBuffer

SharedArrayBuffer 对象用来表示一个通用的,固定长度的原始二进制数据缓冲区。

/**
 * 
 * @param {*} length 所创建的数组缓冲区的大小,以字节(byte)为单位。
 * @returns {SharedArrayBuffer} 一个大小指定的新 SharedArrayBuffer 对象。其内容被初始化为 0。
 */
const buffer = new SharedArrayBuffer(8);

console.log(buffer.byteLength);
// expected output: 8

7、Atomics对象

Atomics 对象提供了一组静态方法用来对 SharedArrayBuffer 对象进行原子操作。

ES9新特性归纳(2018)

1、异步迭代

await可以和for…of循环一起使用,以串行的方式运行异步操作。

async function process(array) {
  for await (let i of array) {
    // doSomething(i);
  }
}

2、Promise.finally()

不管promise状态如何都会执行的回调函数。

new Promise((resolve, reject) => {
  resolve(1);
})
  .then((res) => {
    console.log(res);
  })
  .catch((err) => {
    console.log(err);
  })
  .finally(() => {
    console.log("finally");
  });
// 1
// promise

3、对象的扩展运算符

(…)运算符在数组中可以怎样使用,在对象就可以怎样使用。

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

// 数组合并
const arr = [...arr1, ...arr2];
console.log(arr);

const obj1 = { a: 1 };
const obj2 = { b: 2 };

// 对象合并
const obj = { ...obj1, ...obj2 };
console.log(obj);

// [1, 2, 3, 4, 5, 6]
// {a: 1, b: 2}

4、正则的扩展

①dotAll/s

正则表达式中,点(.)是一个特殊字符,代表任意的单个字符,但是有两个例外。一个是四个字节的 UTF-16 字符,这个可以用u修饰符解决;另一个是行终止符。
所谓行终止符,就是该字符表示一行的终结。以下四个字符属于”行终止符“。

  • U+000A 换行符(\n
  • U+000D 回车符(\r
  • U+2028 行分隔符(line separator)
  • U+2029 段分隔符(paragraph separator)

ES2018 引入s修饰符,使得.可以匹配任意单个字符。
这被称为dotAll模式,即点(dot)代表一切字符。所以,正则表达式还引入了一个dotAll属性,返回一个布尔值,表示该正则表达式是否处在dotAll模式。

const re = /foo.bar/s;
// 另一种写法
// const re = new RegExp('foo.bar', 's');

re.test('foo\nbar') // true
re.dotAll // true



console.log(/./.test(1));
console.log(/./.test("1"));
console.log(/./.test("\n"));
console.log(/./.test("\r"));
console.log(/./.test("\u{2028}"));
// true
// true
// false
// false
// false

// 使用s修饰符
console.log(/./s.test(1));
console.log(/./s.test("1"));
console.log(/./s.test("\n"));
console.log(/./s.test("\r"));
console.log(/./s.test("\u{2028}"));
// true
// true
// true
// true
// true

正则中可以使用的修饰符有i(不区分大小写),g(全局(global)匹配),m(多(more)行匹配),y(匹配必须从剩余的第一个位置开始),u(**只匹配最近的一个字符串;不重复匹配; **),s

②具名组匹配
console.log("2020-07-10".match(/(\d{4})-(\d{2})-(\d{2})/));
// ["2020-07-10", "2020", "07", "10", index: 0, input: "2020-07-10", groups: undefined]

按照 match 的语法,没有使用 g 修饰符,所以返回值第一个数值是正则表达式的完整匹配,接下来的第二个值到第四个值是分组匹配(2020, 07, 10), match 返回值还有几个属性,分别是 index、input、groups。

  • index [匹配的结果的开始位置]
  • input [匹配的字符串]
  • groups [捕获组 ]

所谓的具名组匹配就是命名捕获分组,ES2018允许命名捕获组使用符号?,在打开捕获括号(后立即命名,这样我们就可以通过groups及命名分组获取对应的年月日的值:

console.log("2020-07-10".match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/));

// groups的值
groups: {year: "2020", month: "07", day: "10"}
③反向断言

先行断言指的是,x只有在y前面才匹配,必须写成/x(?=y)/
反向断言,x只有在y后面才匹配,必须写成/(?<=y)x/
在这里插入图片描述
(?<)是后行断言的符号,配合= 、!等使用。

ES10新特性归纳(2019)

1、Array扩展

①Array.prototype.flat()

flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回 。接受一个可选参数,该参数指定嵌套数组应该被展平的级别数。 如果未提供参数,则将使用默认值1:

const arr = [1, [2, [3, [4, [5, [6, 7], 8], 9]]]];
console.log(arr.flat(1));
console.log(arr.flat(5));
console.log(arr.flat(Infinity));

// [1,2,[3, [4, [5, [6, 7], 8], 9]]]
// [1,2,3,4,5,6,7,8,9]
// [1,2,3,4,5,6,7,8,9]
②Array.prototype.flatMap()

flatMap()方法返回一个新数组,不改变原数组。它与 map 和 深度值1的 flat 几乎相同。 flatMap()只能展开一层数组。
flatMap实质上包含两部分功能,一是map,二是flat。

const numbers = [1, 2, 3];

console.log(numbers.map((x) => [x ** 2]).flat());
console.log(numbers.flatMap((x) => [x ** 2]));

// [1,4,9]
// [1,4,9]

2、String.trimStart()/String.trimEnd()

作用是去掉字符串左边的空格/去掉字符串右边的空格。

const str = "   hello world   ";
console.log(str.trimStart());
console.log(str.trimEnd());
console.log(str.trim());

// "hello world   "
// "   hello world"
// "hello world"

3、Symbol.description

只读属性,返回 Symbol 对象的可选描述的字符串。

const symbol = Symbol("symbol");
console.log(symbol.description); // symbol
console.log(symbol.description === "symbol"); // true

4、Object.fromEntries()

es8中对象添加了一个entries()静态方法,这个方法返回一个给定对象自身可枚举属性的键值对数组 ,Object.fromEntries()方法与 Object.entries() 正好相反,可以将键值对列表转换为一个对象 。

const obj = {
  x: 1,
  y: 2,
};

const entries = Object.entries(obj);

console.log(entries);
console.log(Object.fromEntries(entries));

// [["x",1],["y":2]]
// {x:1,y:2}

只要符合entries结构的都可以使用Object.fromEntries(entries)将键值对列表转换为一个对象,比如Map:

// 通过 Object.fromEntries, 可以将 Map 转化为 Object:
const map = new Map([ ['foo', 'bar'], ['baz', 42] ]);
console.log(Object.fromEntries(map)); // { foo: "bar", baz: 42 }

5、catch Building

es10允许我们在捕获异常时省略catch的参数:

// es10以前
try {
  throw new Error();
} catch (error) {
  console.log("fail");
}

// es10
try {
  throw new Error();
} catch {
  console.log("fail");
}

6、Function.prototype.toString()

Function.prototype.toString() 方法返回一个表示当前函数源代码的字符串

function test(a) {
  // es10以前不返回注释部分
  console.log(a);
}
console.log(test.toString());

// function test(a) {
//  // es10以前不返回注释部分
//  console.log(a);
// }

在这里插入图片描述

7、JSON扩展

JSON 内容可以支持包含 U+2028行分隔符 与 U+2029段分隔符。
在这里插入图片描述
在这里插入图片描述
在 ES10 JSON.stringify 会用转义字符的方式来处理 超出范围的 Unicode 展示错误的问题,因为 JSON 都是被编码成 UTF-8,所以遇到 0xD800–0xDFFF 之内的字符会因为无法编码成 UTF-8 进而导致显示错误。在 ES10 它会用转义字符的方式来处理这部分字符而非编码的方式,这样就会正常显示了。JSON 被归为ECMAScript的子集,在之前,JSON不是ECMAScript的子集,从而导致有些可以在JSON中包含的字符,不能够在ECMAScript的字面量中出现:
这次改变之后,我们在编码的时候就不需要再去区分是JSON还是ECMAScript了。

// \uD83D\uDE0E  emoji 多字节的一个字符
console.log(JSON.stringify('\uD83D\uDE0E')) // "😎"

// 如果我们只去其中的一部分  \uD83D 这其实是个无效的字符串
// 之前的版本 ,这些字符将替换为特殊字符,而现在将未配对的代理代码点表示为JSON转义序列
console.log(JSON.stringify('\uD83D')) // "\ud83d"

ES11新特性归纳(2020)

1、空值处理

当查询某个属性时,经常会遇到,如果没有该属性就会设置一个默认的值。

const a = 0;
const b = a || 1;
console.log(b);

// 1

我们在使用||运算符时, 变量值为 0 就是 false ,所以我们会看到上述结果会输出1,但是很多时候我们希望b的输出结果就是a的值0。es11提出了空值合并运算符(??),当左侧操作数为 null 或undefined 时,返回右侧的操作数,否则返回左侧的操作数。

const a = 0;
const b = a ?? 1;
console.log(b);

// 0

2、可选链

可选链可以使我们在查询具有多层级的对象时,不再需要进行冗余的各种前置校验。

const a = {
  b: {
    c: {
      d: {
        e: "111",
      },
    },
  },
};

// es11前
const value = a && a.b && a.b.c && a.b.c.d && a.b.c.d.e;
console.log(value);

// es11:可选链
const value2 = a?.b?.c?.d?.e;
console.log(value2);

可选链中的 ? 表示如果问号左边表达式有值, 就会继续查询问号后面的字段 ,可以大量简化类似繁琐的前置校验操作 。

3、Promise.allSettled()

返回一个在所有给定的promise已被决议或被拒绝后决议的promise,并带有一个对象数组,每个对象表示对应的promise结果。

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => reject('我是失败的Promise_1'));
const promise4 = new Promise((resolve, reject) => reject('我是失败的Promise_2'));
const promiseList = [promise1,promise2,promise3, promise4]
Promise.allSettled(promiseList)
.then(values=>{
  console.log(values)
});

![image.png](https://img-blog.csdnimg.cn/img_convert/16b088c885eab2c8d16e512202c2e2f1.png#clientId=u64c13299-7f9b-4&from=paste&height=125&id=uc21f25d3&margin=[object Object]&name=image.png&originHeight=125&originWidth=649&originalType=binary&ratio=1&size=11201&status=done&style=none&taskId=uacc3c0ef-cfee-4ab5-b792-d145c76ca52&width=649)

4、import

按需加载,为了首屏渲染速度更快,很多时候都是按需加载。
定义 add.js:

export function add(a, b) {
      return a + b
}

在入口文件中导入:

import { add } from './add.js' // 静态导入,不管用不用,先导入进来,相对于动态导入效率较低     console.log(add(3, 4)) // 静态引入时调用 add.js 中的 add()     

// import() 方法动态导入,返回结果是一个promise,成功的值是所导入的模块     import('./add.js').then((module) => {
	console.log(module.add(3, 5))
})

5、BigInt

对于js来说,最大取值范围是2的53次方:

console.log(2 ** 53);
console.log(2 ** 53 + 1);
console.log(Number.MAX_SAFE_INTEGER);
// 9007199254740992
// 9007199254740992
// 9007199254740991

es11为我们提供了第七种新的原始数据类型,BigInt,表示一个任意精度的整数,可以表示超长数据,可以超出2的53次方 。

// 声明BigInt:1、在数字后加上 n 2、用 BigInt() 将数字转为大整型
console.log(100n, typeof 100n) // 100n bigint
console.log(BigInt(100), typeof BigInt(100)) // 100n bigint

// BigInt和Number的区别,BigInt和Number不是严格相等的,但是宽松相等的。
console.log(Object.prototype.toString.call(100)) // [object Number]
console.log(Object.prototype.toString.call(100n)) // [object BigInt]
console.log(100 == 100n) // true
console.log(100 === BigInt(100)) // false

// 不能对小数进行大整数转换
console.log(1n)
// console.log(1.3n) // 报错:Uncaught SyntaxError: Invalid or unexpected token

// 运算结果带小数会被自动取整
console.log(4n / 2n) // 2n
console.log(5n / 2n) // 2n

// 一个正整数后面加上n就转换成了大整型,在数组排序中认为4n大于4,但是在逻辑上4n==4
let arr = [4, 4n, 2, 2n, -10, -10n, -1, -1n, 0, 0n]
console.log(fnSort(arr)) // [-10, -10n, -1, -1n, 0, 0n, 2, 2n, 4, 4n]

// BigInt和String的比较
console.log(2n) // 2n
console.log(2n + '') // '2'

6、globalThis

Javascript 在不同的环境获取全局对象有不通的方式:

  • node 中通过 global
  • web 中通过 window, self

es11提出的globalThis一句话总结就是:无论是在node环境还是web中,全局作用域中的 this 可以通过globalThis访问,不必担心它的运行环境 。

7、String.prototype.matchAll()

  • matchAll() 方法返回一个包含所有匹配正则表达式及分组捕获结果的迭代器 ;
  • 使用: str.matchAll(regexp) ;

字符串处理的一个常见场景是想要匹配出字符串中的所有目标子串:

const str =
  "es2015/es6 es2016/es7 es2017/es8 es2018/es9 es2019/es10 es2020/es10";
const reg = /(es\d+)\/es(\d+)/g;

const matchs = [];
for (let match of str.matchAll(reg)) {
  matchs.push(`${match[1]}-es${match[2]}`);
}
console.log(matchs);
// ["es2015-es6", "es2016-es7", "es2017-es8", "es2018-es9", "es2019-es10", "es2020-es10"]

matchAll() 是返回一个迭代器,对大数据量的场景更友好 。

8、for…in遍历机制

JavaScript 中通过for-in遍历对象时 key 的顺序是不确定的,因为规范没有明确定义,并且能够遍历原型属性让for-in的实现机制变得相当复杂,不同 JavaScript 引擎有各自根深蒂固的不同实现,很难统一。
es11不要求统一属性遍历顺序,而是对遍历过程中的一些特殊 Case 明确定义了一些规则:

  • 遍历不到 Symbol 类型的属性
  • 遍历过程中,目标对象的属性能被删除,忽略掉尚未遍历到却已经被删掉的属性
  • 遍历过程中,如果有新增属性,不保证新的属性能被当次遍历处理到
  • 属性名不会重复出现(一个属性名最多出现一次)
  • 目标对象整条原型链上的属性都能遍历到
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值