详解ECMAScript2019/ES10新属性


Posted in Javascript onDecember 06, 2019

每年都有一些新的属性进入ECMA262标准,今年发布的ECMAScript2019/ES10同样也有很多新的特性,本文将会挑选一些普通开发者会用到的新属性进行深入的解读。

Array.prototype.flat()

The flat() method creates a new array with all sub-array elements concatenated into it recursively up to the specified depth. -- MDN

简单来说flat这个函数就是按照一定的深度depth将一个深层次嵌套的数组拍扁, 例子:

const nestedArr = [1, 2, [3, 4, [5, 6, [7, [8], 9]]], 10]
console.log(nestedArr.flat())
// [1, 2, 3, 4, [5, 6, [7, [8], 9]], 10]
console.log(nestedArr.flat(2))
// [1, 2, 3, 4, 5, 6, [7, [8], 9], 10]
console.log(nestedArr.flat(3))
// [1, 2, 3, 4, 5, 6, 7, [8], 9, 10]
console.log(nestedArr.flat(4))
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(nestedArr.flat(Infinity))
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

由上面的例子可以看出flat会按照指定的深度depth将一个数组扁平化,如果需要将数组完全拍扁变成一维数组,则指定depth为无限大,即是Infinity,相反如果不指定深度,其默认值是1。

Array.prototype.flatMap()

The flatMap() method first maps each element using a mapping function, then flattens the result into a new array. It is identical to a map() followed by a flat() of depth 1, but flatMap() is often quite useful, as merging both into one method is slightly more efficient. -- MDN

简单来说flatMap等于一个数组先调用完map函数再调用flat函数将其扁平化,扁平化的深度固定为1,先通过一个简单的例子感受一下:

const myArr = [1, 2, 3]
myArr
 .map(n => [n * n]) // [[1], [4], [9]]
 .flat() // [1, 4, 9]

// 用flatMap可以一步到位
myArr.flatMap(n => [n * n]) // [1, 4, 9]

从上面的例子来看flatMap如果只是将flat和map做了一个简单的组合好像可有可无,其实不然,flatMap有个强大的功能是可以在map的时候添加和删除元素,这个无论是map还是filter都没有这个功能。

要想删除某一个元素只需要在mapper函数里面返回一个空的数组[], 而增加元素只需在mapper函数里面返回一个长度大于1的数组,具体可以看下面的例子:

// 假如我们想要删除掉原数组里面所有的负数,同时将单数转换为一个复数和1
const a = [5, 4, -3, 20, 17, -33, -4, 18]
//    |\ \ x  |  | \  x  x  |
//    [4,1, 4,  20, 16,1,     18]
a.flatMap(n =>
 (n < 0) ? []: // 删除负数
 (n % 2 == 0) ? [n] : // 保留复数
         [n - 1, 1] // 单数变为一个复数和1
)
// [4, 1, 4, 20, 20, 16, 1, 18]

Object.fromEntries()

The Object.fromEntries() method transforms a list of key-value pairs into an object. --MDN

fromEntries方法将一个iterable对象返回的一系列键值对(key-value pairs)转换为一个object。先看一个简单的例子理解一下:

// key-value pairs数组
const entriesArr = [['k1', 1], ['k2', 2]]
console.log(Object.fromEntries(entriesArr)
// {k1: 1, k2: 2}

const entriesMap = new Map([
 ['k1', 1],
 ['k2', 2]
]) // {"k1" => 1, "k2" => 2}
console.log(Object.fromEntries(entriesMap))
// {k1: 1, k2: 2}

再来看一个自定义的iterable对象例子深入理解一下:

const iteratorObj = {
 [Symbol.iterator]: function () {
  const entries = [['k1', 1], ['k2', 2]]
  let cursor = 0

  return {
   next() {
    const done = entries.length === cursor
    
    return {
     value: done ? undefined : entries[cursor++],
     done
    }
   }
  }
 }
}
Object.fromEntries(iteratorObj) // {k1: 1, k2: 2}

这个方法有一个用途就是对object的key进行filter,举个例子:

const studentMap = {
 student1: {grade: 80},
 student2: {grade: 50},
 student3: {grade: 100}
}
const goodStudentMap = Object.fromEntries(
 Object
  .entries(studentMap)
  .filter(([_, meta]) => meta.grade >= 60)
)
console.log(goodStudentMap)
// {student1: {grade: 80}, student3: {grade: 100}}

String.prototype.trimStart

这个方法很简单,就是返回一个将原字符串开头的空格字符去掉的新的字符串,例子:

const greeting = '  Hello world! '
console.log(greeting.trimStart())
// 'Hello world! '

这个方法还有一个别名函数,叫做trimLeft,它们具有一样的功能。

String.prototype.trimEnd

这个方法和trimStart类似,只不过是将原字符串结尾的空格字符去掉,例子:

const greeting = ' Hello world! '
console.log(greeting.trimEnd())
// ' Hello world!'

这个方法也有一个别名函数,叫做trimRight, 它们也具有一样的功能。

Symbol.prototype.description

The read-only description property is a string returning the optional description of Symbol objects. -- MDN

ECMAScript2019给Symbol对象添加了一个可选的description属性,这个属性是个只读属性,看看例子:

console.log(Symbol('desc').description)
// desc
console.log(Symbol.for('desc').description)
// desc

// 一些内置的Symbol也有这个属性
console.log(Symbol.iterator.description)
// Symbol.iterator

// 如果初始化时没有带description,这个属性会返回一个undefined,因为这样才说这个属性是可选的
console.log(Symbol().description)
// undefined

// 这个属性是只读的,不能被设置
Symbol.iterator.description = 'mess it'
console.log(Symbol.iterator.description)
// Symbol.iterator

这个新的属性只要是为了方便开发者调试,不能通过比较两个Symbol对象的description来确定这两个Symbol是不是同一个Symbol:

var s1 = Symbol("desc")
var s2 = Symbol("desc")
console.log(s1.description === s2.description)
// true
console.log(s1 === s2)
// false

try catch optional binding

ECMAScript2019之后,你写try...catch时如果没必要时可以不用声明error:

// ECMAScript2019之前,你一定要在catch里面声明error,否则会报错
try {
 ...
} catch (error) {

}
// 可是有时候,你确实用不到这个error对象,于是你会写这样的代码
try {
 ...
} catch (_) {
 ...
}

// ECMAScript2019后,你可以直接这样写了
try {
 ...
} catch {
 ...
}

虽然这个新属性可以让你省略掉error,可是我觉得开发者应该避免使用这个属性,因为在我看来所有的错误都应该被处理,至少应该被console.error出来,否则可能会有一些潜在的bug,举个例子:

let testJSONObj
try {
 testJSONObj = JSON.prase(testStr)
} catch {
 testJSONObj = {}
}
console.log(testJSONObj)

以上代码中无论testStr是不是一个合法的JSON字符串,testJSONObj永远都是一个空对象,因为JSON.parse函数名写错了,而你又忽略了错误处理,所以你永远不会知道这个typo。

稳定的排序 Array.prototype.sort

ECMAScript2019后Array.sort一定是个稳定的排序。什么是稳定排序?所谓的稳定排序就是:假如没排序之前有两个相同数值的元素a[i]和a[j],而且i在j前面,即i < j,经过排序后元素a[i]依然排在a[j]元素的前面,也就是说稳定的排序不会改变原来数组里面相同数值的元素的先后关系。看个例子:

var users = [
 {name: 'Sean', rating: 14},
 {name: 'Ken', rating: 14},
 {name: 'Jeremy', rating: 13}
]
users.sort((a, b) => a.rating - b.rating)
// 非稳定的排序结果可能是
// [
//  {name: 'Jeremy', rating: 13}, 
//  {name: 'Ken', rating: 14}, 
//  {name: 'Sean', rating: 14}
// ]
// 虽然Sean和Ken具有同样的rating,可是非稳定的排序不能保证他们两个的顺序在排序后保持不变

// ECMAScript2019后,Array.sort将是一个稳定的排序,也就是说它可以保证Sean和Ken两个人的顺序在排序后不变
// [
//  {name: 'Jeremy', rating: 13}, 
//  {name: 'Sean', rating: 14}, 
//  {name: 'Ken', rating: 14}
// ]

改进Function.prototype.toString()

ECMAScript2019之前,调用function的toString方法会将方法体里面的空格字符省略掉,例如:

function hello() {
 console.log('hello word')
}

console.log(hello.toString())
//'function hello() {\nconsole.log('hello word')\n}'

ECMAScript2019之后,要求一定要返回函数源代码(保留空格字符)或者一个标准的占位符例如native code,所以ECMAScript2019之后,以上的输出会变为:

console.log(hello.toString())
//"function hello() {
// console.log('hello word')
//}"

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery动画3.创建一个带遮罩效果的图片走廊
Aug 24 Javascript
基于javascript制作微博发布栏效果
Apr 04 Javascript
分享12个非常实用的JavaScript小技巧
May 11 Javascript
Bootstrap编写导航栏和登陆框
May 30 Javascript
JavaScript中的splice方法用法详解
Jul 20 Javascript
babel基本使用详解
Feb 17 Javascript
VUE开发一个图片轮播的组件示例代码
Mar 06 Javascript
基于Vue实现支持按周切换的日历
Sep 24 Javascript
JavaScript函数apply()和call()用法与异同分析
Aug 10 Javascript
JS学习笔记之贪吃蛇小游戏demo实例详解
May 29 Javascript
JavaScript本地储存:localStorage、sessionStorage、cookie的使用
Oct 13 Javascript
原生JavaScript实现购物车
Jan 10 Javascript
ES6的异步操作之promise用法和async函数的具体使用
Dec 06 #Javascript
原生JavaScript实现滑动拖动验证的示例代码
Dec 06 #Javascript
微信小程序 自定义弹窗实现过程(附代码)
Dec 05 #Javascript
Nuxt v-bind绑定img src不显示的解决
Dec 05 #Javascript
微信小程序swiper左右扩展各显示一半代码实例
Dec 05 #Javascript
微信小程序顶部导航栏可滑动并选中放大
Dec 05 #Javascript
微信小程序实现点击按钮后修改颜色
Dec 05 #Javascript
You might like
JS BASE64编码 window.atob(), window.btoa()
2021/03/09 Javascript
Jquery 基础学习笔记之文档处理
2009/05/29 Javascript
JavaScript高级程序设计(第3版)学习笔记13 ECMAScript5新特性
2012/10/11 Javascript
iframe异步加载实现点击左边菜单加载右边内容实例讲解
2013/03/04 Javascript
JavaScript用Number方法实现string转int
2014/05/13 Javascript
使用JavaScript脚本无法直接改变Asp.net中Checkbox控件的Enable属性的解决方法
2015/09/16 Javascript
jQuery实现的简单百分比进度条效果示例
2016/08/01 Javascript
js中用cssText设置css样式的简单方法
2016/09/19 Javascript
js实现刷新页面后回到记录时滚动条的位置【两种方案可选】
2016/12/12 Javascript
微信小程序微信支付接入开发实例详解
2017/04/12 Javascript
微信小程序 本地数据读取实例
2017/04/27 Javascript
vue获取当前激活路由的方法
2018/03/17 Javascript
vue添加axios,并且指定baseurl的方法
2018/09/19 Javascript
利用Promise自定义一个GET请求的函数示例代码
2019/03/20 Javascript
JavaScript eval()函数定义及使用方法详解
2020/07/07 Javascript
JavaScript canvas实现跟随鼠标移动小球
2021/02/09 Javascript
[40:19]完美世界DOTA2联赛PWL S3 Rebirth vs CPG 第二场 12.18
2020/12/19 DOTA
python读取csv文件示例(python操作csv)
2014/03/11 Python
Python单链表简单实现代码
2016/04/27 Python
Python注释详解
2016/06/01 Python
Python 实现购物商城,含有用户入口和商家入口的示例
2017/09/15 Python
浅谈Python 多进程默认不能共享全局变量的问题
2019/01/11 Python
python项目对接钉钉SDK的实现
2019/07/15 Python
简单了解Python读取大文件代码实例
2019/12/18 Python
html5 桌面提醒:Notifycations应用介绍
2012/11/27 HTML / CSS
美国最流行的男士时尚网站:Touch of Modern
2018/02/05 全球购物
Perfume’s Club中文官网:西班牙美妆在线零售品牌
2020/08/24 全球购物
CHRONEXT英国:您的首选奢华腕表目的地
2020/03/30 全球购物
阿迪达斯越南官网:adidas越南
2020/07/19 全球购物
飞利信loadrunner和软件测试笔试题
2012/09/22 面试题
晚会邀请函范文
2014/01/24 职场文书
倡议书格式
2014/04/14 职场文书
四风问题自查自纠工作情况报告
2014/10/28 职场文书
离婚起诉书范本
2015/05/18 职场文书
复兴之路观后感
2015/06/02 职场文书
微前端qiankun改造日渐庞大的项目教程
2022/06/21 Javascript