简介
ES9是ECMA协会在2018年6月发行的一个版本,因为是ECMAScript的第九个版本,所以也称为ES9.
明天咱们解说一下ES9的新个性。
ES9引入了3大个性和2个小的个性,咱们接下来一一解说。
异步遍历
在ES6中,引入了同步iteration的概念,随着ES8中的Async操作符的援用,在ES9中引入了异步遍历的新个性Async iteration。
具体的内容能够参考我之前的文章 [ES9的新个性:异步遍历Async iteration]()
Rest/Spread操作符和对象构建
Rest和Spread的操作符都是 ... , 只不过应用的场景和目标不一样。
rest次要用在对象的解构,目前只反对对象的解构和不确定的参数形容。
Spread次要用在字面量对象的构建上。
上面咱们别离来介绍:
Rest
如果用在对象的解构中,除了曾经手动指定的属性名之外,rest将会拷贝对象其余的所有可枚举(enumerable)的属性。
const obj = {foo: 1, bar: 2, baz: 3};const {foo, ...rest} = obj; // Same as: // const foo = 1; // const rest = {bar: 2, baz: 3};
如果用在参数中,rest示意的是所有剩下的参数:
function func({param1, param2, ...rest}) { // rest operator console.log('All parameters: ', {param1, param2, ...rest}); // spread operator return param1 + param2;}
留神,在Obj字面量中,rest运算符只能放在obj的最顶层,并且只能应用一次,还要放在最初。
const {...rest, foo} = obj; // SyntaxErrorconst {foo, ...rest1, ...rest2} = obj; // SyntaxError
当然你还能够嵌套应用rest运算符:
const obj = { foo: { a: 1, b: 2, c: 3, }, bar: 4, baz: 5,};const {foo: {a, ...rest1}, ...rest2} = obj;// Same as:// const a = 1;// const rest1 = {b: 2, c: 3};// const rest2 = {bar: 4, baz: 5};
Spread
spread次要被用来开展对象,可能被开展对象的属性肯定要是可枚举的enumerable。
> const obj = {foo: 1, bar: 2};> {...obj, baz: 3}{ foo: 1, bar: 2, baz: 3 }
如果对象的属性key一样,那么前面属性值会笼罩之前的属性值:
> const obj = {foo: 1, bar: 2, baz: 3};> {...obj, foo: true}{ foo: true, bar: 2, baz: 3 }> {foo: true, ...obj}{ foo: 1, bar: 2, baz: 3 }
创立和拷贝对象
应用Object.assign和Spread操作符能够很不便的进行对象的拷贝。
咱们看一个最简略的对象拷贝的例子:
const clone1 = {...obj};const clone2 = Object.assign({}, obj);
然而这样的拷贝有个毛病,就是只能拷贝自有的可枚举的属性。
并且拷贝之后对象的prototypes是Object.prototype,也就是说没有继承被拷贝对象的prototype。
> Object.getPrototypeOf(clone1) === Object.prototypetrue> Object.getPrototypeOf(clone2) === Object.prototypetrue> Object.getPrototypeOf({}) === Object.prototypetrue
如果想要同时拷贝对象的prototype,则能够这样做:
const clone1 = {__proto__: Object.getPrototypeOf(obj), ...obj};const clone2 = Object.assign( Object.create(Object.getPrototypeOf(obj)), obj);
或者指定对象内置的__proto__属性,或者从obj的prtotype创立一个新的对象。
留神,对象内置的__proto__属性只在局部浏览器中反对。
Object.assign和spread只能拷贝可枚举的属性,如果是set,get属性或者想要拷贝属性的attributes(writable, enumerable),那么就须要用到咱们之前讲到的Object.getOwnPropertyDescriptors。
const clone1 = Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj));const clone2 = Object.create( Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));~~> 留神,咱们应用的所有的拷贝都是浅拷贝。如果被拷贝的对象外部又有对象的话,拷贝的只是这个对象的援用
const original = { prop: {} };
const clone = Object.assign({}, original);
console.log(original.prop === clone.prop); // true
original.prop.foo = 'abc';
console.log(clone.prop.foo); // abc
## Spread和bject.assign() 的区别assgin在拷贝对象的时候,会调用相应属性的set办法,而spread不会。举个例子,咱们先给Object.prototype定义一个set办法:
Object.defineProperty(Object.prototype, 'foo', {
set(value) { console.log('SET', value);},
});
const obj = {foo: 123};
而后看一下拷贝的区别:
Object.assign({}, obj)
SET 123
{}{ ...obj }
{ foo: 123 }
能够看到assign会触发set办法,而spread不会。另外,如果对象属性是不可写的,那么assign将会报错,而spread不会。咱们先定义一个不可写的对象:
Object.defineProperty(Object.prototype, 'bar', {
writable: false,value: 'abc',
});
看下赋值操作:
const tmp = {};
tmp.bar = 123;
TypeError: Cannot assign to read only property 'bar'Object.assign({}, obj)
TypeError: Cannot assign to read only property 'bar'{ ...obj }
{ bar: 123 }
# 正则表达式ES9的正则表达式新个性能够参考我的文章 [ES9的新个性:正则表达式RegExp]()# promise.finallypromise除了then和catch办法之外,还引入了新的finally办法。和java中的finally一样,promise.finally肯定会被执行。
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
和java一样,咱们能够在finally中做一些资源清理的工作:
let connection;
db.open()
.then(conn => {
connection = conn;return connection.select({ name: 'Jane' });
})
.then(result => {
...
})
···
.catch(error => {
// handle errors
})
.finally(() => {
connection.close();
});
下面的例子中,咱们开启了一个数据库的连贯,在应用完之后,咱们在finally中对其进行close操作。# 模板文字和带标签的模板文字模板文字和带标签的模板文字是在ES6中引入的,在ES9中进行了修改。咱们先看下什么是模本文字,模板文字(Template literals)就是在反引号中输出的文字,在其中能够应用${···})来进行变量的解析,并且还反对回车换行。
const firstName = 'Jane';
console.log(`Hello ${firstName}!
How are you
today?`);
// Output:
// Hello Jane!
// How are you
// today?
而带标签的模板文字是指在模板文字之前放上一个函数调用:
String.raw\u{4B}
'\u{4B}'
这里String.raw被称为tag function,咱们看下raw的定义:
raw(template: TemplateStringsArray, ...substitutions: any[]): string;
下面的代码还能够改写为:
String.raw\u004B
'\u004B'
`\u{4B}`和 `\u004B` 都是字符K的unicode示意。下面的raw其实能够这样示意:
function tagFunc(tmplObj, substs) {
return { Cooked: tmplObj, Raw: tmplObj.raw,};
}
咱们能够这样应用:
tagFunc\u{4B}
;
{ Cooked: [ 'K' ], Raw: [ '\u{4B}' ] }
> 本文作者:flydean程序那些事> > 本文链接:[http://www.flydean.com/ecmascript-9/](http://www.flydean.com/ecmascript-9/)> > 本文起源:flydean的博客> > 欢送关注我的公众号:「程序那些事」最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!