yangkean / blog

official blog
5 stars 0 forks source link

谈谈 ES7、ES8、ES9 和 Stage 3 的那些事儿 #9

Open yangkean opened 6 years ago

yangkean commented 6 years ago

前言

我在下面对于标准和实现的说法可能并不规范,但为了便于大家理解,我模糊了标准和实现之间的区别。另外,除了新增特性外,ECMAScript 标准还会对语言本身原有的语法等杂项 (misc) 进行微调,为了保持本文的主线一致,我将忽略这些杂项,只讲述每个 ECMAScript 标准新增的特性 (feature) 的我感觉比较有用的内容 (没错,我就是想偷懒),如果你对杂项有兴趣的话,可以参见 es2016plus 的 misc 栏进行了解和学习,另外也可以参考其中的各种兼容性情况。

ES6 作为多年来 JavaScript 的重大版本变革,受到 JavaScript 开发者们的普遍欢迎。我在 16 年底第一次接触到 ES6 的时候也是欣喜若狂,这比徐公 (ES5) 美多了!经过一个月的学习就立即在个人项目中使用了起来,十分酸爽,而后无论个人项目还是公司项目中我都使用 ES6。也正是从 ES6 (ES2015) 开始,JavaScript 版本发布变为年更,即每年发布一个新版本,以年号标识版本,也就有了这篇文章要讲的 ES7 (ES2016)、ES8 (ES2017)、ES9 (ES2018),以及什么是 Stage 3。不要紧张,我知道很多人可能连 ES6 都还没学完,但其实除了 ES6,后面的这几个版本增加的内容并不多,况且有些内容还蛮有用的,所以,不妨了解下吧。:)

有请一号男嘉宾 —— ES7 出场

孟x旁白:这是由 ECMA International (ECMA 国际) 向我们推荐的男嘉宾。

大家好,我今年 2 岁,来自日内瓦,有两项主要技能,很高兴认识大家。

孟x旁白:请说说你的两项主要技能,请大家为男嘉宾打 call。

好的,我分别介绍一下。

Array.prototype.includes(searchElement[, fromIndex])

在 ES6 中我们有 String.prototype.includes() 可以查询给定字符串是否包含一个子串,而在 ES7 中,我们在数组中也可以用 Array.prototype.includes 查找是否包含某个元素了。元素比较用的是 ===,值得一提的是,即使实际上 NaN !== NaN,但常识告诉我们他们应该相等,所以用这个函数测试 NaN 时,我们很高兴地得到了我们应得到的值。但素,另一个让大家可能会奇怪的是,这个函数认为 +0 和 -0 是相等的,真是表里不一啊,差评!我要给委员会寄刀片!!!脱离这苦海无望了。

'Sam Yang'.includes('Yang') // true

const arr = [1, 3, 5, 2, '8', NaN, -0]
arr.includes(1) // true
arr.includes(1, 2) // false
arr.includes('1') // false
arr.includes(NaN) // true
arr.includes(+0) // true

幂操作符 - **

相信在你要计算某个数的 x 次方时,一定用过 Math.pow()。现在,我们终于可以只用一个普通的操作符就实现幂运算了。虽然这个操作符为二元操作符中最高的 (但低于一元操作符),但是诸如 2 * 5 ** 2 的操作我还是建议用括号括起来,这样会更加一目了然。和除 ++—- 的一元操作符一起使用时,都必须使用括号明确意图,否则会因为歧义而报错,同样的,我建议都使用括号明确意图,炫技在工程上并不是聪明的举动。

Math.pow(5, 2) // 25
5 ** 2 // 25

// 相当于 2 * (5 ** 2)
2 * 5 ** 2 // 50

点评

孟 x:让我们来看看是否有人留灯。(噔~噔~噔~)全灰,很遗憾,希望你能找到你的归宿!我们来看下一位。

有请二号男嘉宾 —— ES8 出场

孟x旁白:这也是由 ECMA International 向我们推荐的男嘉宾。

大家好,我今年 1 岁,来自日内瓦,有三项主要技能,很高兴认识大家。接下来我介绍下自己。

对象新增的静态方法

1.Object.values(obj)

返回一个由 给定对象自有可枚举 属性值组成的数组。值的顺序是 for...in 遍历对象时的顺序。

const object = {
  a: 'somestring',
  b: 42,
  c: false
};

Object.values(object) // ["somestring", 42, false]

2.Object.entries(obj)

和 Object.values(obj) 是类似的,只是返回的数组的元素是键值对数组。

const object = {
  a: 'somestring',
  b: 42,
  c: false
};

Object.entries(object) // [["a", "somestring"], ["b", 42], ["c", false]]

3.Object.getOwnPropertyDescriptors(obj)

返回一个由 给定对象 的所有 自有 属性的属性描述符组成的对象。

const object = {
  a: 42
};

Object.getOwnPropertyDescriptors(object)
// {a: {value: 42, writable: true, enumerable: true, configurable: true}}

String padding

这是我觉得的一个很有趣的特性。

1.String.prototype.padStart(targetLength [, padString])

用 padString 这个字符串重复填充当前的字符串的头部,以至当前字符串能达到给定长度,即 targetLength。padString 默认使用的是空格。

'Sam Yang'.padStart(15, 'good') // "goodgooSam Yang"
'Sam Yang'.padStart(5, 'good') // "Sam Yang"
'Sam Yang'.padStart(10) // "  Sam Yang"

2.String.prototype.padEnd(targetLength [, padString])

与 String.prototype.padStart 是类似的,只是这是插在当前字符串尾部而已。

'Sam Yang'.padEnd(15, 'good') // "Sam Yanggoodgoo"

有人可能会说,这有啥用捏?还真别说,我遇到了。一般情况下这个方法可以用来格式化字符串,比如让字符串拥有统一的缩进。但我之前遇到了合并字符串时的问题,像 (126).toString(2) 在转化为二进制字符串时,竟然把最前面的 0 去掉了,这有时是很坑爹的,详见我的文章 用 ArrayBuffer 来截取二进制数据中的字符

async 函数

哇!这个不得了,好多人好早就估计开始用了,用了都说爽,简直是异步编程神器,不过它在 ES8 才入标准就是了。这个我提一提,展开了讲可以讲很多。

这个函数可以说是 Promise 和 Generator 的结合体,因为我们可以同时得到 Promise 的可信任性和 Generator 的同步性,做到以同步的方式写可以信任的异步代码。

function resolveAfter2Seconds() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}

// 用 async 声明异步函数
async function asyncCall() {
  console.log('calling');
  var result = await resolveAfter2Seconds(); // await 会等到它后面的表达式执行完毕才继续执行
  console.log(result);
}

asyncCall();
// calling
// resolved

更具体的使用方法可以参见 async function

点评

孟 x:让我们来看看是否有人留灯。(噔~噔~噔~)Java 为你亮了灯,你要选择他吗?

ES8:我拒绝。

孟 x:好,希望你能找到你的归宿。我们有请下一位。

有请三号男嘉宾 —— ES9 出场

孟x旁白:这还是由 ECMA International 向我们推荐的男嘉宾。

Hello, everyone. My name is ES9 and I am from Geneva. I am zero year old this year. 所以我现在还是个宝宝!谢谢大家!(全场传来阵阵掌声)

因为我还是个宝宝,所以在长大中,会有一些新东西不断加到我身上,我先说下我现在有的吧。而且因为我刚出来没多久,知道我的人并不多,所以介绍我的资料比较少点,接下来基本是我的自嘲。

对象的 rest/spread 属性

rest 属性跟数组及函数中的 rest 运算符用法很类似,是用 ... 将剩余的属性放入一个对象中。

const {a, ...rest} = {a: 1, b: 2, c: 3}
rest // {b: 2, c: 3}

const spread = {b: 2, c: 3}
const obj = {a: 1, ...spread}
obj // {a: 1, b: 2, c: 3}

Promise.prototype.finally(onFinallyFunc)

Promise 新增的这个实例方法跟 try...catch...finally 里 的 finally 很像,就是无论一个 promise 是被 fulfilled 还是被 rejected,都将执行传给这个方法的 onFinallyFunc 函数。

Promise.resolve(1)
.then((val) => {
    console.log(`fulfilled: ${val}`)
})
.catch((err) => {
    console.log(`rejected: ${err}`)
})
.finally(() => {
    console.log('hello world')
})
// fulfilled: 1
// hello world

Promise.reject(1)
.then((val) => {
    console.log(`fulfilled: ${val}`)
})
.catch((err) => {
    console.log(`rejected: ${err}`)
})
.finally(() => {
    console.log('hello world')
})
// rejected: 1
// hello world

其实还有很多东西等着加入我。(台下私语:看起来是个潜力股)

点评

孟 x:让我们来看看留灯情况。(噔~噔~噔~)TypeScript、React、Angular、Vue 均为你爆灯,你可以选择他们中的其中一个。

ES9(思考良久):我的选择是 —— React。

孟 x:让我们祝福他们!

ES9 & React:xx 蒸蛋糕,是真的爱你❤️。

Stage 3

孟 x:

这一期节目,我们见识了三位新人,他们各怀绝技,有惊喜有遗憾。但是,有些嘉宾可能还在娘胎,他们也有可能很优秀,让我们来了解下从娘胎到出生的五个阶段:Strawman(Stage 0,稻草人),Proposal(Stage 1,提议),Draft(Stage 2,草案),Candidate(Stage 3,候选)以及 Finished(Stage 4,完成)。分别对应着:有机会写入标准,讨论实现方法和可能存在的挑战,明确地用正式文档语言描述语法和语义,需要实现和用户的反馈来做细微的改进,准备好进入 ECMAScript 标准。前面三种处于细胞状态,最后一种意味着已经在标准中了,而 Stage 3 则是意味着很大程度能进入标准,也就是极有可能成为我们的下一位男嘉宾。当前的 Stage 3 基本没有被什么浏览器实现。我就说下其中一个较多浏览器实现的吧。

string trimming

这个是用来给给定字符串清除字符串周围指定方向的 whitespace 字符 的,但不影响原字符串。因为 trim 方法会清除两边,而有时我们可能只需要清除一边。

let str = '  Sam Yang  '
str.trim() // "Sam Yang"
str.trimLeft() // "Sam Yang  "
str.trimRight() // "  Sam Yang"
str // '  Sam Yang  '

结尾

就是这样,欢迎大家收看这期的《非 ES 勿扰》。

Reference

Rabbitzzc commented 6 years ago

总结的不错哦,不过...运算符就很奇怪呀!希望能有对象copy和deepcopy的函数出现。

szhang6 commented 5 years ago

学识与幽默并存:)