ECMAScript系列更新 ES6~ES12
1.ES6 (ES2015)
1.1 Class
JavaScript 是一种使用原型链的语言。 早期像面向对象这样的概念都是通过原型链来做的,比较复杂,Class 终于在 ES6 中引入了。
class Animal {
constructor(name, color) {
this.name = name;
this.color = color;
} // This is a property on the prototype chain
toString() {
console.log('name:' + this.name + ', color:' + this.color);
} }
var animal = new Animal('myDog', 'yellow');
animal.toString();console.log(animal.hasOwnProperty('name')); //true
console.log(animal.hasOwnProperty('toString')); // false
console.log(animal.__proto__.hasOwnProperty('toString')); // true
class Cat extends Animal
{ constructor(action)
{ super('cat', 'white'); this.action = action; }
toString() {
console.log(super.toString());
} }
var cat = new Cat('catch');
cat.toString();
console.log(cat instanceof Cat); // true
console.log(cat instanceof Animal); // true
1.2 module
每个模块都有自己的命名空间,避免冲突,使用 import 和 export 来导入导出,默认将 .js 文件视为模块。
1.3 Arrow
function 箭头函数 () => {…}是函数的缩写,有了箭头函数再也不用写 var self = this, var that = this 等类代码。
const add = (a, b) => { return a + b; };
const res = add(1, 2); // 3
const minus = (a, b) => a - b;
const res1 = minus(5, 1); // 4
1.4 函数参数默认值
如果函数不传参数,则使用默认值,更简洁。
function example(height = 5, width = 6) {
const newH = height * 2;
const newW = width * 4;
return newH + newW;
}
example(); // 34 (5*2 + 6*4)
1.5 模板字符串
以前,长字符串的组合使用+号连接,可读性差,使用模板字符串更容易阅读。
const firstName = 'water';
const lastName = 'fish';// not use template
literalconst name = 'Hello, My name is' + firstName + ', ' + lastName;
// use template literalconst
nameWithLiteralString = `Hello, My name is ${firstName}, ${lastName}`;
1.6 解构
const arr = [1, 2, 3, 4, 5];
const [one, two, three] = arr;
console.log(one); // 1
console.log(two); // 2
...
// To skip certain values
const [first,,,,last] = arr;
console.log(first); // 1
console.log(last); // 5
// Objects can also be destructurized and assigned
const student = { name: 'waterfish', age: 28, };
const {name, age, city} = student;
console.log(name);// waterfish
console.log(age); // 28
1.7 spread
操作符 const arr1 = ['A', 'B'];
const arr2 = ['0', ...arr1, '1', '2'];
conslog.log(arr2); // [0, A, B, 1, 2]
用三个点…表示,Array 可以扩展,而如果是 Object,则根据 key-value 进行扩展。
1.8 对象属性缩写
因为构成 newCustomer 对象属性的 name、age 的 key、value 相同,所以省略 value。
const name = 'waterfish', age = 28;
// Before ES6, we must write like this
const customer = { name: name, age: age, }; // //
{name: 'waterfish', age: 28}
// After ES6, we can do it
const newCustomer = { name, age, };
// {name: 'waterfish', age: 28}
1.9 Promise Promise
是一种解决异步(非同步)写法的方案,比原来的 callback 写法更优雅。使用 Promise 可以解决 hell callback。
const waitSecond = new Promise((resolve, reject) => {
setTimeout(resolve, 1000); });
waitSecond .then(() => {
console.log('hello after 1 second.');
// output this line after 1 second
return waitSecond; }) .then(() => {
console.log('World after 2 sceond.');
// output this line after 2second });
1.10 let, const 替换 var
let:通用变量,可以重写。
const:一旦声明,其内容不可修改。因为数组和对象都是指针,所以可以在不改变指针的情况下增加或减少它们的内容。
2.ES7 (ES2016)
2.1 Array.prototype.includes()
用于判断数组中是否包含指定值,如果包含则返回 true,否则,返回 false。因为返回布尔值,比 indexOf 的语义化更加清晰。
const arr = [1, 2, 3, 4, 5];
arr.include(3); // true
if (arr.include(3)) { ... }
// ... Equivalent to the previous writing of indexOf arr.indexOf(3);
// 2 (return its array position)
// If you want to write it in the if, you must add `> -1`, which is not as clear as the include in ES7 in terms of semanticsif (arr.indexOf(3) > -1) { ... }
2.2 指数运算符
console.log(2 ** 10); // 1024// equal to
console.log(Math.pow(2, 10)); // 1024
3.ES8 (ES2017)
发布了一个更完美的 async,await,直接让异步的写法看起来像同步的。
3.1 async, await 异步函数是使用 async 关键字声明的函数,其中允许使用 await 关键字。 async 和 await 关键字使基于 Promise 的异步行为能够以更简洁的方式编写,避免显式配置 Promise 链的需要。
async test() {
try {
const result = await otherAsyncFunction();
console.log(result); // output
result } catch(e) {
console.log(e); // Can catch errors if otherAsyncFunction() throws an error } }
3.2 Object.values()
返回对象自身属性的所有值,不包括继承的值。
const exampleObj = { a: 1, b: 2, c: 3, d: 4 };console.log(Object.value(exampleObj)); // [1, 2, 3, 4];// To do the same thing before, use the following notation. much verboseconst values = Object.keys(exampleObj).map((key) => exampleObj[key]);
3.3 Object.entries()
返回一个可枚举的键,value 中存储的是键的值。 const Obj = { a: 1, b: 2, c: 3, d: 4 };console.log(Object.entries(Obj)); // [[a, 1], [b, 2], [c, 3], [d, 4]]; // Usually used with forfor (const [key, value] of Object.entries(Obj)) { console.log(`key: ${key}, value: ${value}`);}// key: a, value: 1// key: b, value: 2// key: c, value: 3// key: d, value: 4
3.4 padStart() & padEnd()
您可以在字符串的开头或结尾添加额外的内容,并将其填充到指定的长度。过去,这些功能通常是通过 lodash 等通用帮助工具包引入 的。 String.padStart(fillingLength, FillingContent);// If the content to be filled is too much and exceeds the fill length,// it will be filled from the leftmost to the upper limit of the length,// and the excess will be truncated 最常用的情况应该是金额,填指定长度,不足补 0。 // padStart'100'.padStart(5, 0); // 00100// If the content to be padded exceeds the padding length. Then fill in from the left to the upper limit of the length'100'.padStart(5, '987'); // 98100 // padEnd'100'.padEnd(5, 9); // 10099// If the content to be padded exceeds the padding length. Then fill in from the right to the upper limit of the length'100'.padEnd(5, '987'); // 10098
3.5 trailing comma
ECMAScript 2017 支持函数参数中的尾随逗号。 function f(p) {}function f(p) {} (p) => {};(p) => {}; 3.6 Object.getOwnPropertyDescriptors() 获取您自己的描述符,一般开发业务需求通常不会使用这些描述符。 const exampleObj = { a: 1, b: 2, c: 3, d: 4 };Object.getOwnPropertyDescriptors(exampleObj);// {a: {…}, b: {…}, c: {…}, d: {…}}// a: {value: 1, writable: true, enumerable: true, configurable: true}// b: {value: 2, writable: true, enumerable: true, configurable: true}// c: {value: 3, writable: true, enumerable: true, configurable: true}// d: {value: 4, writable: true, enumerable: true, configurable: true}// __proto__: Object
3.7 共享数组缓冲区(shared array buffer)
SharedArrayBuffer 是原始二进制数据的固定长度缓冲区,类似于 ArrayBuffer。可用于在共享内存上创建数据,与 ArrayBuffer 不同,SharedArrayBuffer 不能分离。
3.8 Atomics object Atomics
对象提供一组静态方法来对 SharedArrayBuffer 执行原子操作。如果一个多线程同时在同一个位置读写数据,原子操作保证了正在操作的数据符合预期:即在上一个子操作结束后执行下一个,操作不中断。 可以说是针对 Node.Js 中多线程 Server 的开发而加强的功能,在前端开发中使用的机会相当低,目前 Chrome 已经支持。
4.ES9 (ES2018)
4.1 await loop
在异步函数中,有时需要在同步 for 循环中使用异步(非同步)函数。for 循环本身还是同步的,整个 for 循环会在循环中的异步函数执行完之前执行完,然后里面的异步函数会一个一个执行。ES9 加入了异步迭代器,允许 await 配合使用 for 循环逐步执行异步操作。
async function process(array) { for await (const i of array) { doSomething(i); } }
4.2 promise.finally()
无论是成功(.then())还是失败(.catch()),都会在 Promise 之后执行的代码。
function process() { process1() .then(process2) .then(process3) .catch((err) => { console.log(err); }) .finally(() => { console.log(`it must execut no matter success or fail`); }); }
4.3 Rest & Spread
const myObject = { a: 1, b: 2, c: 3,};const { a, ...r } = myObject;// a = 1// r = { b: 2, c: 3 }// Can also be used in function input parametersfunction restObjectInParam({ a, ...r }) { console.log(a); // 1 console.log(r); // {b: 2, c: 3}}restObjectInParam({ a: 1, b: 2, c: 3,});
5.ES10 (ES2019)
5.1 Array.prototype.flat() & Array.prototype.flatMap()
const arr1 = [1, 2, [3, 4]];arr1.flat(); // [1, 2, 3, 4] const arr2 = [1, 2, [3, 4, [5, 6]]];arr2.flat(); // [1, 2, 3, 4, [5, 6]]// Pass in a number in flat, representing the flattening deptharr2.flat(2); // [1, 2, 3, 4, 5, 6] 下面是 flatMap 方法: let arr = ['water', '', 'fish']; arr.map((s) => s.split(''));// [[w, a, t, e, r], [], [f, i, s, h] arr.flatMap((s) => s.split(''));// [w, a,t,e,r, , f, i, s, h]
5.2 String.prototype.trimStart() & String.prototype.trimEnd()
trimStart() 方法从字符串的开头删除空格,trimLeft() 是该方法的别名。 const greeting = ' Hello world! '; console.log(greeting); // expected output: Hello world! ; console.log(greeting.trimStart()); // expected output: Hello world! ; trimEnd() 方法删除字符串末尾的空格,trimRight() 是该方法的别名。 const greeting = ' Hello world! '; console.log(greeting); // expected output: Hello world! ; console.log(greeting.trimEnd()); // expected output: Hello world!;
5.3 Object.fromEntries()
将键值对列表转换为对象。 const entries = new Map([ ['foo', 'bar'], ['baz', 42], ]);const obj = Object.fromEntries(entries);console.log(obj);// expected output: Object { foo: bar, baz: 42 }
5.4 String.prototype.matchAll matchAll()
方法返回一个迭代器,遍历将字符串与正则表达式匹配的所有结果,包括捕获组。 const regexp = /t(e)(st(\d?))/g; const str = 'test1test2'; const array = [...str.matchAll(regexp)]; console.log(array[0]); // expected output: Array [test1, e, st1, 1] console.log(array[1]); // expected output: Array [test2, e, st2, 2]
5.5 BigInt
const theBiggestInt = 9007199254740991n;const alsoHuge = BigInt(9007199254740991);// ↪ 9007199254740991nconst hugeString = BigInt('9007199254740991');// ↪ 9007199254740991nconst hugeHex = BigInt('0x1fffffffffffff');// ↪ 9007199254740991nconst hugeBin = BigInt( '0b11111111111111111111111111111111111111111111111111111' );// ↪ 9007199254740991n
6.ES11 (ES2020)
6.1 Promise.allSettled() Promise.allSettled()
方法返回一个 Promise,当所有给定的 Promise 都已完成或被拒绝时,该 Promise 就会完成,其中每个对象都描述每个 Promise 的结果。 当您有多个不依赖于彼此成功完成的异步任务时,或者当您总是想知道每个 Promise 的结果时通常会使用它。 相反,如果任务相互依赖、或者您希望其中任何一个 Promise 失败后则立即拒绝,则由 Promise.all() 返回的 Promise 可能更合适。
const promise1 = Promise.resolve(3);const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo') );const promises = [promise1, promise2];Promise.allSettled(promises).then((results) => results.forEach((result) => console.log(result.status)) );// expected output:// fulfilled// rejected
6.2 Optional ?
const username = user?.name || 'guest';
6.3 Nullish
coalescing operator ?? 在 JavaScript 中,0、null 或 undefined 会自动转为 false,但有时候希望将返回值设置为 0。 const username = user.level ?? 'no level';// output 0. if level is not available, it becomes 'no level'.
6.4 Dynamic-import
动态引入 el.onclick = () => { import(`/js/logger.js`) .then((module) => { module.doSomthing(); }) .catch((err) => { handleError(err); }); };
6.5 GlobalThis
全局 globalThis 属性包含全局 this 值,类似于全局对象。
function canMakeHTTPRequest() { return typeof globalThis.XMLHttpRequest === 'function'; }console.log(canMakeHTTPRequest());// expected output (in a browser): true
7.ES12 (ES2021)
7.1 Promise.any()
Promise.any() 接受一个可迭代的 Promise 对象,每当可迭代对象中的任何一个 Promise fullfill 时它都返回一个 Promise,其中包含已 fullfill 的 Promise 的值。如果所有的 Promise reject 则返回 AggregateError 对象,其是 ERROR 对象的一个子类,默认搜集所有 Error 并分组。
const p1 = new Promise((resolve) => { setTimeout(() => { resolve('p1 resolved value'); }, 1000); });const p2 = new Promise((resolve) => { setTimeout(() => { resolve('p2 resolved value'); }, 500); });const p3 = new Promise((resolve) => { setTimeout(() => { resolve('p3 resolved value'); }, 1800); });Promise.any([p1, p2, p3]).then((value) => { console.log(value); }); // p2 resolved value
7.2 逻辑赋值运算符
在开发过程中,可以使用在 ES2020 引入的逻辑运算符 ||、&& 和 ?? (Nullish coalescing operator)来解决一些问题。而 ES2021 会提出 ||= , &&= , ??= ,概念类似于 += :
let b = 2; b += 1;// equal to b = b + 1let a = null; a ||= 'some random text'; // a become to'some random text'// equal a = a || 'some random text'let c = 'some random texts'; c &&= null; // c become to null// equal to c = c && nulllet d = null; d ??= false; // d become to false// equal to d = d ?? false
7.3 弱引用(WeakRef)
WeakRef 对象持有对对象的弱引用,称为其目标或引用对象。对对象的弱引用是不会阻止对象被垃圾收集器回收的引用。 普通(或强)引用将对象保存在内存中,当一个对象不再具有任何强引用时,JavaScript 引擎的垃圾收集器可能会销毁该对象并回收其内存,如果发生这种情况,您将无法再从弱引用中获取对象。
8.ES13 (ES2022)
期待不一样的东西
原文链接:https://medium.com/