ES11屡试不爽的新特性,你用上了几个


Posted in Javascript onOctober 21, 2020

ES11规范于今年的年初完成,引入了许多新标准,本文讲着重研究下其中几个实用且有趣的新标准

特性抢先知:

  • 私有变量
  • Promise.allSettled
  • BigInt 全新的数据类型
  • Nullish Coalescing Operator 空位合并运算符
  • Optional Chaining Operator 可选链运算符
  • Dynamic Import 动态导入
  • String.prototype.matchAll 新增matchAll
  • globalThis 新增全局对象
  • Module Namespace Exports 导入特定命名空间

私有变量

严格限制一些用于内部使用的Class变量,只需要在变量前 添加# ,就可以使其成为私有变量,并且无法在class外部直接访问

下面我们以一个简单的

class Hero {
  #aggressivity = 0
  constructor (aggressivity){
   this.#aggressivity = aggressivity
  }
  getHurt(){
   return this.#aggressivity
  }
  setAggressivity(aggressivity){
   this.#aggressivity = aggressivity
  }
}

const shooter = new Hero(100)
let hurt = shooter.getHurt()
console.log(hurt) //100
console.log(shooter.#aggressivity) //Error : Uncaught SyntaxError: Private field '#aggressivity' must be declared in an enclosing class

上面代码我们会发现,无法直接进行访问#aggressivity,将抛出异常

只能通过class里进行访问,可通过统一class的公共方法进行统一修改

假设目前射手携带了 狂暴 技能,提升了 10%伤害 ,我们可以通过setAggressivity来修改攻击力

ES11屡试不爽的新特性,你用上了几个

let aggressivity = parseInt(hurt * 1.1)
shooter.setAggressivity(aggressivity)
console.log(shooter.getHurt()) // 110

Promise.allSettled

谈及这个新特性之前,我们先简单回顾下 Promise.all 以及 Promise.race ,推测下为什么需要 Promise.allSettled 这个新特性

Promise.all:可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值

let p1 = new Promise((resolve, reject) => {
 resolve('成功了')
})

let p2 = new Promise((resolve, reject) => {
 resolve('success')
})

let p3 = Promse.reject('失败')

Promise.all([p1, p2]).then((result) => {
 console.log(result) //['成功了', 'success']
}).catch((error) => {
 console.log(error)
})

Promise.all([p1,p3,p2]).then((result) => {
 console.log(result)
}).catch((error) => {
 console.log(error) // 失败了,打出 '失败'
})

Promise.race:返回一个promise,一旦某个Promise触发resolve或者reject,就直接返回该promise结果状态

const promise1 = new Promise((resolve, reject) => {
 setTimeout(resolve, 500, 'one');
});

const promise2 = new Promise((resolve, reject) => {
 setTimeout(resolve, 100, 'two');
});

Promise.race([promise1, promise2]).then((value) => {
 console.log(value);
});
//输出 "two" 因为promise2返回结果比promise1快

有时候我们可能需要知道所有的结果做一些操作,并不关心其执行结果是否成功,在没有Promise.allSettled之前,我们需要自己实现,可通过如下 实现Promise.allSettled

let allSettled = (funcArr) => {
 return new Promise((resolve) => {
  let sttled = 0
  let result = []
  for(let index = 0;index<funcArr.length;index++){
   const element = funcArr[index]
   element
   .then(res => { 
    result[index] = {
     status: 'fulfilled',
     value: res
    }
   })
   .catch(err => { 
    result[index] = {
     status: 'rejected',
     reason: err
    }
   })
   .finally(() => { ++sttled === funcArr.length && resolve(result) })
  }
 })
}

//使用
const promises = [
  Promise.reject('c'),
  Promise.resolve('a'),
  Promise.resolve('b'),
];

allSettled(promises).then(res => {
  console.log(res)
})

// 打印结果
// [{"status":"rejected","reason":"c"},
// {"status":"fulfilled","value":"a"},
// {"status":"fulfilled","value":"b"}]

而Promise.allSettled新特性出来后,我们可以直接使用而不需要单独去实现了

const promises = [
  Promise.reject('c'),
  Promise.resolve('a'),
  Promise.resolve('b'),
];
Promise.allSettled(promises).then(res =>{
 console.log(res)
})
// 打印结果
// [{"status":"rejected","reason":"c"},
// {"status":"fulfilled","value":"a"},
// {"status":"fulfilled","value":"b"}]

返回结果里会将返回一个数组,包含了所有成功与失败的结果,数组每项为对象,均含有 status 属性,对应fulfilled和rejected。

当状态为 fulfilled 时,代表着成功,包含一个 value ,代表着成功的结果

当状态为 rejected 时,代表着失败,包含一个 reason ,代表着失败的原因

BigInt

JS中缺少显式整数类型常常令人困惑。许多编程语言支持多种数字类型,如浮点型、双精度型、整数型和双精度型,但JS却不是这样。在JS中,按照IEEE 754-2008标准的定义,所有数字都以双精度 64位浮点格式 表示。

在此标准下,无法精确表示的非常大的整数将自动四舍五入。确切地说,JS 中的Number类型只能安全地表示-9007199254740991 (-(2^53-1)) 和9007199254740991(2^53-1)之间的整数,任何超出此范围的整数值都可能失去精度。

console.log(9999999999999999);  //10000000000000000

JS 提供 Number.MAX_SAFE_INTEGER 常量来表示 最大安全整数, Number.MIN_SAFE_INTEGER 常量表示最小安全整数:

// 注意最后一位的数字
const A = Number.MAX_SAFE_INTEGER + 1
const B = Number.MAX_SAFE_INTEGER + 2

console.log(Number.MAX_SAFE_INTEGER) //9007199254740991
console.log(A) //9007199254740992
console.log(B) //9007199254740992

console.log(A === B) //true

当数据超出范围就会失去精度,达不到我们预期的结果。

BigInt横空出世,可以在标准JS中执行对大整数的算术运算,不必担心精度损失风险

创建BigInt数据类型的方式非常简单,在整数后面追加 n 即可,或者 通过BigInt()进行创建实例

const bigint = 999999999999999999n
const bigintByMethod = BigInt('999999999999999999')
console.log(bigint) //999999999999999999n
console.log(bigintByMethod) //999999999999999999n
console.log(bigint === bigintByMethod) //true

//布尔值
console.log(BigInt(true)) //1n
console.log(BigInt(false)) //0n

console.log(typeof bigint) //"bigint"

BigInt 与 Number是两种数据类型,无法进行运算,可以进行大小比较

console.log(88n == 88) //true
console.log(88n === 88) //false
console.log(88n+1) //Error =>Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions

BigInt之间, 除了一元加号(+)运算符 外,其他均可用于BigInt

console.log(1n + 2n) //3n
console.log(1n - 2n) //-1n
console.log(+ 1n) //Uncaught TypeError: Cannot convert a BigInt value to a number
console.log(- 1n) //-1n
console.log(10n * 20n) //200n
console.log(23n%10n) //3n
console.log(20n/10n) //2n
......

需要注意的是, 除法运算符会自动向下舍入到最接近的整数

console.log(25n / 10n) //2n
console.log(29n / 10n) //2n

最后还有个注意点就是,Boolean类型和BigInt类型的转换时,处理方式和Number类型,只要 不是0n,BigInt就被视为true

if (5n) {
  // 这里代码块将被执行
}

if (0n) {
  // 这里代码块不会执行
}

Nullish Coalescing Operator 空位合并运算符

新增一个逻辑运算符??,处理null和undefined,工作原理与逻辑or( || )类似,但是与此相反

||如果为真即返回左侧值,否则返回右侧

0 || 5 // return 5
"" || 5 // return 5
"前端公虾米" || 'V5' //return "前端公虾米"

??如果为null或者undefined,即返回右侧,否则返回左侧

0 ?? 5 //return 0
"" ?? 5 //return ""
null ?? 5 // return 5
undefined ?? 5 // return 5
false ?? 5 //return false
NaN ?? 5 // return NaN

在使用该??运算符时,需要注意的是

  • 不可与其他运算符组合使用,例如&&、||
  • 但若使用括号包裹则可以组合使用
"前端公虾米" || undefined ?? "Sneaker" //Uncaught SyntaxError: Unexpected token '??'
"前端公虾米" && undefined ?? "Sneaker" //Uncaught SyntaxError: Unexpected token '??'

("前端公虾米" || undefined) ?? "(๑•̀ㅂ•́)و✧" //"前端公虾米"
("前端公虾米" && null) ?? "一起学习" //"一起学习"

Optional Chaining Operator 可选链运算符

日常开发中,不少开发者会碰到Cannot read property XXX of undefined,抛出无法从未定义的数据中读取某个字段

可选链运算符在查找嵌套对象时,找到链中的第一个 undefined 或者 null 后会立即终止,并返回 undefined ,而不会不断向下查找而导致抛错

const obj = {
 foo: {
  bar: {
   baz: 42,
  },
 },
}
console.log(obj.fo.bar.baz) //Uncaught TypeError: Cannot read property 'bar' of undefined

在诸如此类的对象里,我们通常进行数据安全检查来访问嵌套对象,否则将抛错
if(obj&&obj.foo&&obj.foo.bar){
 console.log(obj.foo.bar.baz) // 42
}

在可选链运算符可使用的现在,我们只需这样进行属性的读取

console.log(obj?.foo?.bar?.baz) //42
      
console.log(obj.foo.bar?.baz) //42

Dynamic Import 动态导入

在标准的import导入中,是静态导入的,所有被导入的模块是在加载时就被编译的,无法按需编译。当我们需要条件导入的时候,都只能使用 require() .

但现在,我们有办法改善此类情况了,因为动态导入可以有效的减少未使用代码的编译,可以提高首屏加载速度,按需加载。

那么,为什么我们需要动态导入呢?

  • 静态导入消耗加载时间,很多模块并非首屏需要渲染
  • 静态导入会在导入时消耗大量内存
  • 可能会存在有些模块在加载时不存在
  • 减少一些有条件依赖的副作用
//通用导入方式
import("/module/sneaker/test.js")
.then(module => {
 //模块相关操作
})

//await
const getModule = await import("/module/sneaker/test.js")

//通过async await
const getUserInfo = async (hasLogin) => {
 if(!hasLogin){
 const user = await import("/module/sneaker/user.js")
  user.getInfo()
 }
}

matchAll

基于String原型上的一个新方法,允许我们匹配一个字符串和一个正则表达式,返回值是所有匹配结果的迭代器。

可以通过 for...of 遍历或者 操作符...Array.from 将结果迭代器转换成数组

const string = 'Hello Sneaker,Where is the library?'
const regex = /[A-W]/g
const matches = string.matchAll(regex)

console.log(...matches)
//["H", index: 0, input: "Hello Sneaker,Where is the library?", groups: undefined] 
//["S", index: 6, input: "Hello Sneaker,Where is the library?", groups: undefined] 
//["W", index: 14, input: "Hello Sneaker,Where is the library?", groups: undefined]

globalThis

这是为了提供一种访问全局对象的标准方法。

在浏览器中,我们可以使用 window/self/frames 来访问全局对象,但对于Web Workers只能使用 self ,Node中又完全不同,需要使用 global

globalThis 成为标准之前,获取全局对象我们可能需要这么做

const globalObj = (()=>{
 if(self) return self
 if(window) return window
 if(global) return global
 throw new Error('Sorry!No global obj found')
})
//Browser 
globalThis === window //true

//Webworker
globalThis === self //true

//Node
globalThis === global //true

从此实现全局对象的大一统!

Module Namespace Exports 导入特定命名空间

export * as ns from './module

//等同于
import * as ns from './module'
export {ns}

导入特定命名空间实则并没有导入模块,只是对模块进行转发,导致在此模块中不可直接使用此模块

参考

  • ecma-262
  • MDN

最后

特性很多但有的很有趣,比如可选链和空位合并运算符,屡试不爽,至于有多爽,你试了才知道。新特性平常不写还是容易忽略淡忘的,建议平常可以下意识的经常回顾运用,一起学习一起成长。

到此这篇关于ES11屡试不爽的新特性,你用上了几个的文章就介绍到这了,更多相关ES11 新特性内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
JS 时间显示效果代码
Aug 23 Javascript
document.documentElement的一些使用技巧
Apr 18 Javascript
JavaScript子类用Object.getPrototypeOf去调用父类方法解析
Dec 05 Javascript
jquery实现的横向二级导航效果代码
Aug 26 Javascript
javascript每日必学之基础入门
Feb 16 Javascript
JS简单添加元素新节点的方法示例
Feb 10 Javascript
深入浅析Vue中的 computed 和 watch
Jun 06 Javascript
vue中el-upload上传图片到七牛的示例代码
Oct 19 Javascript
详解微信小程序自定义组件的实现及数据交互
Jul 22 Javascript
微信公众号平台接口开发 获取access_token过程解析
Aug 14 Javascript
vue简单练习 桌面时钟的实现代码实例
Sep 19 Javascript
微信小程序实现打卡签到页面
Sep 21 Javascript
记一次vue跨域的解决
Oct 21 #Javascript
解决Vue项目中tff报错的问题
Oct 21 #Javascript
vue-cli3自动消除console.log()的调试信息方式
Oct 21 #Javascript
js 压缩图片的示例(只缩小体积,不更改图片尺寸)
Oct 21 #Javascript
vue-cli4使用全局less文件中的变量配置操作
Oct 21 #Javascript
Vue全局使用less样式,组件使用全局样式文件中定义的变量操作
Oct 21 #Javascript
js 图片懒加载的实现
Oct 21 #Javascript
You might like
php知道与问问的采集插件代码
2010/10/12 PHP
php与mysql建立连接并执行SQL语句的代码
2011/07/04 PHP
CI框架常用函数封装实例
2016/11/21 PHP
jquery 面包屑导航 具体实现
2013/06/05 Javascript
Jquery AJAX POST与GET之间的区别
2013/11/14 Javascript
JavaScript极简入门教程(三):数组
2014/10/25 Javascript
jQuery实现连续动画效果实例分析
2015/10/09 Javascript
javascript实现的全国省市县无刷新多级关联菜单效果代码
2016/08/01 Javascript
JavaScript基本类型值-Number类型
2017/02/24 Javascript
jQuery实现简单的计时器功能实例分析
2017/08/29 jQuery
JavaScript 中的 this 简单规则
2017/09/19 Javascript
jQuery EasyUI 选项卡面板tabs的使用实例讲解
2017/12/25 jQuery
jQuery 防止相同的事件快速重复触发方法
2018/02/08 jQuery
JS实现瀑布流效果
2020/03/07 Javascript
浅析JavaScript中的事件委托机制跟深浅拷贝
2021/01/20 Javascript
[01:19:35]DOTA2上海特级锦标赛主赛事日 - 3 败者组第三轮#2Fnatic VS OG第二局
2016/03/05 DOTA
[01:01]青春无憾,一战成名——DOTA2全国高校联赛开启
2018/02/25 DOTA
Python函数式编程指南(三):迭代器详解
2015/06/24 Python
Python3.6 Schedule模块定时任务(实例讲解)
2017/11/09 Python
Python2.7环境Flask框架安装简明教程【已测试】
2018/07/13 Python
python pyheatmap包绘制热力图
2018/11/09 Python
python批量将excel内容进行翻译写入功能
2019/10/10 Python
Xadmin+rules实现多选行权限方式(级联效果)
2020/04/07 Python
HTML5拖拽文件到浏览器并实现文件上传下载功能代码
2013/06/06 HTML / CSS
泰国汽车、火车和轮渡票预订网站:Bus Online Ticket
2017/09/09 全球购物
Shopee印度尼西亚:东南亚与台湾市场最大电商平台
2018/06/17 全球购物
应届生求职信写作技巧
2013/10/24 职场文书
办公室文员工作自我评价
2013/12/01 职场文书
会计专业自我评价
2014/02/12 职场文书
微电影大赛策划方案
2014/06/05 职场文书
森林防火宣传标语
2014/06/27 职场文书
活动总结报告怎么写
2014/07/03 职场文书
师范毕业生求职信
2014/07/11 职场文书
机关作风整顿个人整改措施2014
2014/09/17 职场文书
Python快速实现一键抠图功能的全过程
2021/06/29 Python
详解MySQL的主键查询为什么这么快
2022/04/03 MySQL