ECMAScript 2017(ES8)新特性简介
文章目录
- 简介
- Async函数
- 共享内存和原子操作
- Object的新方法
- String的新方法
- 逗号可以添加到函数的参数列表后面了
简介
ES8是ECMA协会在2017年6月发行的一个版本,因为是ECMAScript的第八个版本,所以也称为ES8.
今天我们讲解一下ES8的新特性。
ES8引入了2大特性和4个小的特性,我们接下来一一讲解。
Async函数
我们在ES6中提到了generator,Async函数的操作和generator很类似。
我们看下Async的使用:
//Async 函数定义:
async function foo() {}//Async 函数表达式:
const foo = async function () {};//Async 方法定义:
let obj = { async foo() {} }//Async 箭头函数:
const foo = async () => {};
async函数返回的是一个封装的Promise对象:
async function asyncFunc() {return 123;
}asyncFunc()
.then(x => console.log(x));// 123
如果在函数中抛出异常,则会reject Promise:
async function asyncFunc() {throw new Error('Problem!');
}asyncFunc()
.catch(err => console.log(err));// Error: Problem!
上面的例子中我们在async函数使用的是同步的代码,如果想要在async中执行异步代码,则可以使用await,注意await只能在async中使用。
await后面接的是一个Promise。如果Promise完成了,那么await被赋值的结果就是Promise的值。
如果Promise被reject了,那么await将会抛出异常。
async function asyncFunc() {const result = await otherAsyncFunc();console.log(result);
}// Equivalent to:
function asyncFunc() {return otherAsyncFunc().then(result => {console.log(result);});
}
我们可以顺序处理异步执行的结果:
async function asyncFunc() {const result1 = await otherAsyncFunc1();console.log(result1);const result2 = await otherAsyncFunc2();console.log(result2);
}// Equivalent to:
function asyncFunc() {return otherAsyncFunc1().then(result1 => {console.log(result1);return otherAsyncFunc2();}).then(result2 => {console.log(result2);});
}
也可以并行执行异步结果:
async function asyncFunc() {const [result1, result2] = await Promise.all([otherAsyncFunc1(),otherAsyncFunc2(),]);console.log(result1, result2);
}// Equivalent to:
function asyncFunc() {return Promise.all([otherAsyncFunc1(),otherAsyncFunc2(),]).then([result1, result2] => {console.log(result1, result2);});
}
最后看下如何处理异常:
async function asyncFunc() {try {await otherAsyncFunc();} catch (err) {console.error(err);}
}// Equivalent to:
function asyncFunc() {return otherAsyncFunc().catch(err => {console.error(err);});
}
需要注意的是,如果async中返回的不是Promise,那么将会被封装成为Promise。如果已经是Promise对象的话,则不会被再次封装:
async function asyncFunc() {return Promise.resolve(123);
}
asyncFunc()
.then(x => console.log(x)) // 123
同样的,如果返回一个rejected的Promise对象,则和抛出异常一样的结果:
async function asyncFunc() {return Promise.reject(new Error('Problem!'));
}
asyncFunc()
.catch(err => console.error(err)); // Error: Problem!
如果你只是想触发异步方法,但是并不想等待它执行完毕,那么不使用await:
async function asyncFunc() {const writer = openFile('someFile.txt');writer.write('hello'); // don’t waitwriter.write('world'); // don’t waitawait writer.close(); // wait for file to close
}
共享内存和原子操作
ES7引入了一个新的构造函数SharedArrayBuffer和命名空间Atomics。
在JS中,除了主线程之外,我们还可以创建worker线程,主线程和worker线程之间的通信是通过postMessage方法来进行的。
但是这样的通信方式并不高效。于是引入了SharedArrayBuffer这样的共享空间,来提升消息传输效率。
// main.jsconst worker = new Worker('worker.js');// To be shared
const sharedBuffer = new SharedArrayBuffer( // (A)10 * Int32Array.BYTES_PER_ELEMENT); // 10 elements// Share sharedBuffer with the worker
worker.postMessage({sharedBuffer}); // clone// Local only
const sharedArray = new Int32Array(sharedBuffer); // (B)
上面的例子中,我们创建了一个SharedArrayBuffer,并将这个SharedArrayBuffer通过postMessage的方式发给worker。
我们知道postMessage是以拷贝的方式来发送消息的,但是这是正确使用共享的方式。
我看下在worker中怎么接收这个Buffer:
// worker.jsself.addEventListener('message', function (event) {const {sharedBuffer} = event.data;const sharedArray = new Int32Array(sharedBuffer); // (A)// ···
});
在worker中,我们将sharedBuffer使用Int32Array封装起来,作为Array而使用。
那么我们考虑一个问题,在使用sharedBuffer的过程中,会出现什么问题呢?
因为是共享的,所以可以在多个worker线程中同时被使用。如果在同时被使用的时候就会出现多线程共享数据的问题,也就是并发的问题。
为了解决并发的问题,我们回想一下在java中特别有一个concurrent包,里面有一些Atomic的类,可以执行原子性操作。
在ES8中,同样引入了Atomics,用来进行SharedArrayBuffer的原子性操作。同时,使用Atomics还可以禁止重排序。
Atomics实际操作的Typed Array:Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array or Uint32Array。
注意,这些Array都是SharedArrayBuffer的封装Array。并且都是Int的Array(目前只支持Int类型)。
首先看下Atomics怎么解决数组的并发写入和读取的问题:
Atomics.load(ta : TypedArray<T>, index) : T
Atomics.store(ta : TypedArray<T>, index, value : T) : T
Atomics.exchange(ta : TypedArray<T>, index, value : T) : T
Atomics.compareExchange(ta : TypedArray<T>, index, expectedValue, replacementValue) : T
load和store可以将ta作为一个整体来操作。
看下使用例子:
// main.js
console.log('notifying...');
Atomics.store(sharedArray, 0, 123);// worker.js
while (Atomics.load(sharedArray, 0) !== 123) ;
console.log('notified');
Atomics还提供了wait和notity功能:
Atomics.wait(ta: Int32Array, index, value, timeout)
Atomics.wake(ta : Int32Array, index, count)
当ta[index]的值是value的时候,wait将会使worker等待在ta[index]之上。
而wake,则是将等待在ta[index]上的count个worker唤醒。
Atomics还提供了一系列的操作:
Atomics.add(ta : TypedArray<T>, index, value) : T
Atomics.sub(ta : TypedArray<T>, index, value) : T
Atomics.and(ta : TypedArray<T>, index, value) : T
Atomics.or(ta : TypedArray<T>, index, value) : T
Atomics.xor(ta : TypedArray<T>, index, value) : T
它相当于:
ta[index] += value;
Atomic有一个很棒的作用就是构建lock。我们将会在后面的文章中介绍。
Object的新方法
Object提供了两个遍历的新方法entries和values。
Object.entries(value : any) : Array<[string,any]>
entries返回的是一个数组,里面存储的是key-value对:
> Object.entries({ one: 1, two: 2 })
[ [ 'one', 1 ], [ 'two', 2 ] ]
entries给了我们一个遍历Object的方法:
let obj = { one: 1, two: 2 };
for (let [k,v] of Object.entries(obj)) {console.log(`${JSON.stringify(k)}: ${JSON.stringify(v)}`);
}
// Output:
// "one": 1
// "two": 2
我们可以使用entries来创建Map:
let map = new Map(Object.entries({one: 1,two: 2,
}));
console.log(JSON.stringify([...map]));// [["one",1],["two",2]]
同样的,Object还提供了values方法:
Object.values(value : any) : Array<any>
返回的是一个数组,数组中存放的是Object的value。
除此之外,Object还有一个getOwnPropertyDescriptors新方法。
这个方法返回的是Obj中的属性的描述。所谓属性的描述就是指这个属性是否可写,是否可以数之类:
const obj = {[Symbol('foo')]: 123,get bar() { return 'abc' },
};
console.log(Object.getOwnPropertyDescriptors(obj));// Output:
// { [Symbol('foo')]:
// { value: 123,
// writable: true,
// enumerable: true,
// configurable: true },
// bar:
// { get: [Function: bar],
// set: undefined,
// enumerable: true,
// configurable: true } }
key是Obj中的key,value就是PropertyDescriptors。
虽然在ES6中,Obj已经引入了一个Object.assign()方法用来拷贝properties,但是这个assign只能拷贝具有默认属性值的属性。对于那些具有非默认属性值的属性getters, setters, non-writable properties来说,Object.assign是不能拷贝的。这个时候就需要使用getOwnPropertyDescriptors方法了。
const source = {set foo(value) {console.log(value);}
};
console.log(Object.getOwnPropertyDescriptor(source, 'foo'));
// { get: undefined,
// set: [Function: foo],
// enumerable: true,
// configurable: true }const target1 = {};
Object.assign(target1, source);
console.log(Object.getOwnPropertyDescriptor(target1, 'foo'));
// { value: undefined,
// writable: true,
// enumerable: true,
// configurable: true }
可以看到obj就有一个foo属性,它是一个setter。所以使用assign是不能进行拷贝的。
我们看下怎么使用defineProperties和getOwnPropertyDescriptors来进行拷贝:
const target2 = {};
Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source));
console.log(Object.getOwnPropertyDescriptor(target2, 'foo'));
// { get: undefined,
// set: [Function: foo],
// enumerable: true,
// configurable: true }
除了拷贝属性之外,我们还可以拷贝对象:
const clone = Object.create(Object.getPrototypeOf(obj),Object.getOwnPropertyDescriptors(obj));
String的新方法
String添加了两个新的方法padStart和padEnd。
pad就是填充的意思,我们可以从前面填充也可以从后面填充。我们看下pad的用法:
String.prototype.padStart(maxLength, fillString=' ')
String.prototype.padEnd(maxLength, fillString=' ')
看下具体的使用:
> 'x'.padStart(5, 'ab')
'ababx'
> 'x'.padEnd(5, 'ab')
'xabab'
逗号可以添加到函数的参数列表后面了
在ES8之前,函数的最后一个参数是不允许添加逗号的,但是在ES8中,一切都变得可能。
function foo(param1,param2,
) {}
我们可以在函数的定义中添加逗号。也可以在函数的调用中添加逗号:
foo('abc','def',
);
本文作者:flydean程序那些事
本文链接:http://www.flydean.com/ecmascript-8/
本文来源:flydean的博客
欢迎关注我的公众号:「程序那些事」最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
ECMAScript 2017(ES8)新特性简介相关推荐
- ECMAScript 2021(ES12)新特性简介
简介 ES12是ECMA协会在2021年6月发行的一个版本,因为是ECMAScript的第十二个版本,所以也称为ES12. ES12发行到现在已经有一个月了,那么ES12有些什么新特性和不一样的地方呢 ...
- ECMAScript 2019(ES10)新特性简介
简介 ES10是ECMA协会在2019年6月发行的一个版本,因为是ECMAScript的第十个版本,所以也称为ES10. 今天我们讲解一下ES10的新特性. ES10引入了2大特性和4个小的特性,我们 ...
- ECMAScript 2016(ES7)新特性简介
简介 自从ES6(ECMAScript 2015)在2015年发布以来,ECMAScript以每年一个版本的速度持续向前发展.到现在已经是ECMAScript 2020了. 每个版本都有一些新的特性, ...
- ES6-Promise简介、ES7 新特性及ES8新特性-async和await
目录 ES6-Promise Promise简介 Promise.prototype.then方法 Promise.prototype.catch方法 ES7 新特性 Array.prototype. ...
- JavaScript——ES8新特性
ES8新特性 一.async 和 await 1. async 函数 2. await 表达式 3. 实例 二.对象方法扩展 一.async 和 await async 和 await 两种语法结合可 ...
- Oracle11g新特性简介
转 Oracle 11g 新特性简介https://blog.csdn.net/tianlesoftware/article/details/5134819 Oracle 11g于2007年7月11 ...
- JDK8新特性简介、Lambda表达式、Stream流常用api介绍
JDK8新特性简介.Lambda表达式.Stream流常用api介绍 接口 Java1.8前接口中是不允许有普通方法的,在Java1.8后允许接口中有普通方法,只需要加上default关键字即可: J ...
- ES7/ES8新特性总结
es7新特性 ES2016添加了两个小的特性来说明标准化过程: 数组includes()方法,用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回true,否则返回false. a ** b ...
- ECMAScript 6新特性简介
文章目录 简介 ECMAScript和JavaScript的关系 let和const 解构赋值 数组的扩展 函数的扩展 简介 ECMAScript 6.0(以下简称 ES6)是 JavaScript ...
最新文章
- list mybatis批量保存_mybatis 批量将list数据插入到数据库的实现
- 第20讲:代理的基本原理和用法
- 【转】如何更改VS2010的[默认开发语言]默认环境设置 .
- Blazor带我重玩前端(四)
- 爱前端2018全栈大前端_启动2018年前端工具调查
- 把cpp编译为so_基于VSCode和CMake进行C/C++开发第三讲GCC编译器
- mysql索引 和 es索引_MySQL索引 VS ElasticSearch索引
- 诗与远方:无题(七十二)
- mac docker mysql_Mac操作系统上使用Docker创建MySQL主从数据库
- 【UI】为项目添加类似于淘宝筛选列表勾选的ui-choose
- CSDN第一次写博客时的模板
- 数据库——“该连接已关闭”问题解决方案
- 一粒云盘发布v3.5版本
- [读书笔记] 有效竞品分析
- C++primer第五版课后答案参考
- oracle 12c 容器数据库公共用户去访问pdb数据库
- 解决电脑系统重装后出现多引导项的问题
- 邮件服务器 二级域名,hMailServer+Roundcube+APMServ+希网二级域名+ADSL搭建邮件服务器...
- MYSQL索引3:聚簇索引和非聚簇索引
- 扯ruan蛋的房价,恶心死了我
热门文章
- Python操作FTP服务器实现文件和文件夹的上传与下载,python清理ftp目录下的所有文件和非空文件夹
- 程序员过高工资导致加班?应该降低程序员工资?网友:放过其他苦逼的程序员吧
- Freda的队列 简单模拟
- win10下编译OpenCV的微信二维码库给Dotnet使用
- flash传值php乱码,Flash中出现中文乱码的解决办法,网页模板帮助中心
- nova8se鸿蒙,挖东西:华为nova8SE标准版和高配版哪个好?解析有区别没有?主要的优势在哪里?...
- SQL service基础(九)用户定义数据类型和用户定义函数的概念、创建及使用方法
- power Designer VBS 脚步 通过 excel 生成实体,不用一个一个的输入。
- Linux3._Linux环境基础开发工具使用
- SpringMVC之CRUD和文件上传下载