ES7/ES8新特性
概述
JavaScript,作为一门处于高速发展期的开发语言,正在变的越来越完善、稳定。我们必须拥抱这些变化,并且我们需要把ES8加入到我们的技术栈中。
ECMAScript 是标准化的 JavaScript 语言,1997 年发布了第一版,1998 年和 1999 年发布了第二和第三个版本,之后沉寂 了许多年,直到 Ajax 流行起来后标准工作才再次起步,2009 年发布了第五个版本,自 2015 年起每年发布一个版本。现在为开发者所熟知的ES6就是2015年发布的。
ES7新增特性比较少,在这个版本中,ES7只增加了两种新特性:Array.prototype.includes和Exponentiation Operator(求冥运算)。而在最新的ES8版本中,新增的特性比较多,主要包括:Object.values/Object.entries、字符串填充、Object.getOwnPropertyDescriptor、尾随逗号、异步函数、共享内存和原子等。
ES7 新特性
Array.prototype.includes
Array.prototype.includes用法都容易和简单。它是一个替代indexOf,开发人员用来检查数组中是否存在值,indexOf是一种尴尬的使用,因为它返回一个元素在数组中的位置或者-1当这样的元素不能被找到的情况下。所以它返回一个数字,而不是一个布尔值(开发人员需要实施额外的检查)。在ES6,要检查是否存在值,你需要做一些判断,因为他们没有匹配到值,Array.prototype.indexOf返回-1变成了true(转换成true),但是当匹配的元素为0位置时候,该数组包含元素,却变成了false。
let arr = ['react', 'angular', 'vue']// WRONGif (arr.indexOf('react')) { // 0 -> evaluates to false, definitely as we expected console.log('Can use React') // this line would never be executed}// Correctif (arr.indexOf('react') !== -1) { console.log('Can use React') }
或者使用一点点hack 位运算符 ~ 使代码更加紧凑一些,因为~(位异或)对任何数字相当于-(a + 1)。
let arr = ['react', 'angular', 'vue']// Correctif (~arr.indexOf('react')) { console.log('Can use React') }
在ES7中,使用includes代码格式如下:
let arr = ['react', 'angular', 'vue']// Correctif (arr.includes('react')) { console.log('Can use React') }
let str = 'React Quickly'// Correctif (str.toLowerCase().includes('react')) { // true console.log('Found "react"') }
有趣的是,许多JavaScript库已经实现includes或类似功能contains的功能。常见的有:
jQuery: $.inArray
Underscore.js: _.contains
Lodash: .includes (在版本3或者早期版本中是.contains 和 Underscore一样)
CoffeeScript: in 操作(example)
Darf: list.contains (example)
除了增强了可读性语义化,实际上给开发者返回布尔值,而不是匹配的位置。includes也可以在NaN(非数字)使用。最后,includes第二可选参数fromIndex,这对于优化是有好处的,因为它允许从特定位置开始寻找匹配。
上面的说明例子:
console.log([1, 2, 3].includes(2)) // === true)console.log([1, 2, 3].includes(4)) // === false)console.log([1, 2, NaN].includes(NaN)) // === true)console.log([1, 2, -0].includes(+0)) // === true)console.log([1, 2, +0].includes(-0)) // === true)console.log(['a', 'b', 'c'].includes('a')) // === true)console.log(['a', 'b', 'c'].includes('a', 1)) // === false)
Exponentiation Operator
求幂运算大多数是为开发者做一些数学计算,对于3D,VR,SVG还有数据可视化非常有用。在ES6或者早些版本,你不得不创建一个循环,创建一个递归函数或者使用Math.pow。例如,使用Math.pow创建一个递归箭头函数。
calculateExponent = (base, exponent) => base*((--exponent>1)?calculateExponent(base, exponent):base)console.log(calculateExponent(7,12) === Math.pow(7,12)) // trueconsole.log(calculateExponent(2,7) === Math.pow(2,7)) // true12345
而在ES7/ES2016语法规则中,开发者可以使用更短的语法实现求冥运算。
let a = 7 ** 12let b = 2 ** 7console.log(a === Math.pow(7,12)) // trueconsole.log(b === Math.pow(2,7)) // true1234
许多ES新特性是从其他语言(如CoffeeScript、Ruby)模仿而来。例如,ES7中指数运算符在其他语言的存在形式。
Python: x ** y
CoffeeScript: x ** y
F#: x ** y
Ruby: x ** y
Perl: x ** y
Lua, Basic, MATLAB: x ^ y
ES8
ES8 在上一个版本的基础上增加了很多新特性!ES8标准已于2017年6月发布。
Object.values/Object.entries
在ES8 /ES2017之前,Javascript开发者需要迭代一个对象的自身属性时候不得不用Object.keys,通过迭代且使用obj[key]获取value值返回一个数组。
let obj = {a: 1, b: 2, c: 3} Object.keys(obj).forEach((key, index)=>{ console.log(key, obj[key]) })
而在ES6/ES2015中,使用for/of会稍微好点。
let obj = {a: 1, b: 2, c: 3}for (let key of Object.keys(obj)) { console.log(key, obj[key]) }
虽然使用老方式for/in也许会非常好用,但是当它碰到迭代枚举属性时,会破坏像prototype和tostring的属性得到意想不到的值。在ES8版本中,JordanHarband提出的Object.entries引入了一个entry概念。对象是键值对的数据结构,每个键值对都是entry。Object.entries(x)强制转换x为对象,并以数组的方式返回其可枚举的自定义字符串。例如:
>>Object.entries({foo:1,bar:2}) [['foo',1],['bar',2]]
与Object.entries非常相似,Object.values返回一个数组,其值为可枚举的字符串键值属性。
>> Object.values({foo:1,bar:2}) [1,2]
Object.entries( )和Object.values( )输出结果如下:
Object.entries(value:any):Array <[string,any]> Object.values(value:any):Array <any> 12
字符串填充
String.prototype.padStart 和 String.prototype.padEnd在javascript字符操作是一个不错的体验,引入padStart 和 padEnd,可以使开发人员更好地控制字符串原语。
padStart()在开始部位填充,返回一个给出长度的字符串,填充物给定字符串,把字符串填充到期望的长度。一个经典例子是使用空格创建列,使用它,可以帮助我们格式化一些字符串。
console.log('react'.padStart(10).length) // " react" is 10console.log('backbone'.padStart(10).length) // " backbone" is 10
padEnd顾名思义就是从字符串的尾端右边开始填充。例如:
console.log('react'.padEnd(10, ':-)')) // "react:-):-" is 10console.log('backbone'.padEnd(10, '*')) // "backbone**" is 10
Object.getOwnPropertyDescriptors
Object.getOwnPropertyDescriptors返回对象obj所有自身属性描述。这是一个多参数版本的Object.getOwnPropertyDescriptors(obj,propName)将会返回obj中propName属性的一个单独描述。
在ES5中,ECMAScript中没有单个方法来简化两个对象之间的正确拷贝。开发者要使用Object.assign()来拷贝对象, Object.assign()分配属性只有copy和定义新的属性。当我们使用更加复杂对象和类原型,这可能会出问题。
Object.getOwnPropertyDescriptors允许创建真实的对象浅副本并创建子类,它通过给开发者描述符来做到这一点.在Object.create(prototype, object)放入描述符后,返回一个真正的浅拷贝。
Object.create( Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj) )1234
异步函数
异步函数(或者async/await)特性操作是Promise最重要的功能。使用Promises处理Async函数的一种普遍写法如下所示:
function fetchData(url) { return fetch(url) .then(request => request.text()) .then(text => { return JSON.parse(text); }) .catch(err => { console.log(`Error: ${err.stack}`); }); }
在ES8中,新增async和await关键字,我们可以利用它来实现同步读取操作。在内部,Async功能与生成器的功能相同,但是却不能转换为Generator Functions。使用ES2017中的Async函数如下:
async function fetchData(url) { try { let request = await fetch(url); let text = await request.text(); return JSON.parse(text); } catch (err) { console.log(`Error: ${err.stack}`); } }
有了 async/await,我们的代码执行异步看起来像执行同步一样。可以从头到尾读起来非常简单和易懂,因为出现结果顺序和函数题中从头到尾顺序一样啊!
共享内存与原子操作
当内存被共享时,多个线程可以并发读、写内存中相同的数据。原子操作可以确保那些被读、写的值都是可预期的,即新的事务是在旧的事务结束之后启动的,旧的事务在结束之前并不会被中断。
Atomic 对象类似于 Math 对象,拥有许多静态方法,所以我们不能把它当做构造函数。 引入此功能后,低级别Atomics命名空间对象和一个SharedArrayBuffer构造函数,能够让开发人员开发共享多个service worker和核心线程之间的SharedArrayBuffer对象的数据,从而可以改善worker之间的协调。
转载声明:本文转载自异步社区
原文链接:https://www.epubit.com/articleDetails?id=N026a2e57-5bf8-4d5d-bc56-19a755d37b87
- 点赞
- 收藏
- 关注作者
评论(0)