ECMAScript 2018(ES9)新特性简介

时间:2022-09-02 14:29:10

简介

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; // SyntaxError
const {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.prototype
true
> Object.getPrototypeOf(clone2) === Object.prototype
true
> Object.getPrototypeOf({}) === Object.prototype
true

如果想要同时拷贝对象的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));
~~ > 注意,我们使用的所有的拷贝都是浅拷贝。如果被拷贝的对象内部又有对象的话,拷贝的只是这个对象的引用 ~~~js
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.finally

promise除了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/

本文来源:flydean的博客

欢迎关注我的公众号:「程序那些事」最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

ECMAScript 2018(ES9)新特性简介的更多相关文章

  1. ECMAScript 2016(ES7)新特性简介

    简介 自从ES6(ECMAScript 2015)在2015年发布以来,ECMAScript以每年一个版本的速度持续向前发展.到现在已经是ECMAScript 2020了. 每个版本都有一些新的特性, ...

  2. ECMAScript 2017(ES8)新特性简介

    目录 简介 Async函数 共享内存和原子操作 Object的新方法 String的新方法 逗号可以添加到函数的参数列表后面了 简介 ES8是ECMA协会在2017年6月发行的一个版本,因为是ECMA ...

  3. ECMAScript 2019(ES10)新特性简介

    简介 ES10是ECMA协会在2019年6月发行的一个版本,因为是ECMAScript的第十个版本,所以也称为ES10. 今天我们讲解一下ES10的新特性. ES10引入了2大特性和4个小的特性,我们 ...

  4. ECMAScript 2020(ES11)新特性简介

    目录 简介 动态imports import.meta export加强 BigInt matchAll() globalThis Promise.allSettled() ??操作符 ?.操作符 总 ...

  5. ECMAScript 2021(ES12)新特性简介

    简介 ES12是ECMA协会在2021年6月发行的一个版本,因为是ECMAScript的第十二个版本,所以也称为ES12. ES12发行到现在已经有一个月了,那么ES12有些什么新特性和不一样的地方呢 ...

  6. 细解JavaScript ES7 ES8 ES9 新特性

    题记:本文提供了一个在线PPT版本,方便您浏览 细解JAVASCRIPT ES7 ES8 ES9 新特性 在线PPT ver 本文的大部分内容译自作者Axel Rauschmayer博士的网站,想了解 ...

  7. ES6新特性简介

    ES6新特性简介 环境安装 npm install -g babel npm install -g babel-node //提供基于node的REPL环境 //创建 .babelrc 文件 {&qu ...

  8. ECMAScript 6新特性简介

    目录 简介 ECMAScript和JavaScript的关系 let和const 解构赋值 数组的扩展 函数的扩展 简介 ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言 ...

  9. ES9新特性

    这篇文章主要介绍ES2018(ES9)的新特性, 以及使用方法 JS是一门跨平台的语言, ES6也就是ECMAScript 2015 花费了5年的时间敲定, 是一次非常大的改版, 之后每年都有一个小版 ...

随机推荐

  1. 贪吃蛇的java代码分析(二)

    代码剖析 贪吃蛇是一款十分经典的小游戏,对初入coding的朋友来说,拿贪吃蛇这样一个案例来练手十分合适,并不高的难度和成功后的成就感都是学习所必须的.下面我将依照我当时的思路,来逐步分析实现的整个过 ...

  2. js中的tostring()方法

    http://blog.sina.com.cn/s/blog_85c1dc100101bxgg.html js中的tostring()方法 (2013-11-12 11:07:43) 转载▼ 标签: ...

  3. 伙计,给我来一杯package.json!不加糖

    前言:夜深了,我熬了一锅热气腾腾的package.json,给大家端上来,希望大家喜欢 json和JS对象的区别 package.json,顾名思义,它是一个json文件,而不能写入JS对象. 所以我 ...

  4. maven 出现错误 -source 1.5 中不支持 diamond 运算符

    mvn clean package -DskipTests 出现如下错误: -source 1.5 中不支持 diamond 运算符 [ERROR] (请使用 -source 7 或更高版本以启用 d ...

  5. udp/tcp流程

    udp: 1.创建套接字 socket 2.绑定本地ip/port bind 3.收发数据 sendto/recvfrom 4.关闭套接字 close tcp客户端: 1.创建套接字 socket 2 ...

  6. puppet 横向扩展(二)

    Table of Contents 1. 概述 2. 实验环境 3. 实验步骤 3.1. 机器B 的环境 3.1.1. 安装puppetmaster 以及 apache passenger 3.1.2 ...

  7. Flask需要登录权限的装饰器写法

    def wapper(func): def inner(*args,**kwargs): if not request.cookies.get("username"): retur ...

  8. 10.16JS日记

    1.parseint() 2.parsefloat() 这两个单词运行的时候遇到第一个非数字就结束了 3.var a="hello word"  a这个变量为字符串,每一个字母为字 ...

  9. HGOI20180822 五校联考卷

    T1 [题目意思]给出下列程序片段,预测程序运行结果 输入文件为T(T<=200)组数据,每组数据有个n(n<=1014) 输出文件为T行,每行一个数据,表示fun(n)的值 simple ...

  10. 将IP地址转化为整数

    $ip = 'IP地址';echo $intip = sprintf('%u',ip2long($ip)); //转换为无符号整型echo long2ip($intip);//将整型转换为ip