es6es7es8常⽤新特性总结(超实⽤)
本⽂标题有误导性,因为我其实想写node8的新特性,说实话⼀下⼦从node v1.x跳跃到node 8.x+ 真有点受宠若惊的感觉。⼀直觉得node 数组、对象、序列等的处理没有python⽅便,因为需要借助外部的⼀些包⽐如underscore /lodash才能实现,但是接下来是见证奇迹的时刻,es6/7/8让node代码变的更简洁、更易懂。
Node.js的优点之⼀就是前后端⽤同⼀种语⾔,本质上还是js,因此可以通过babel来使nodejs⽀持对应的ECMAScript。
⽬录
如何让Nodejs⽀持对应的ES
ES6常⽤新特性
let && const
iterable类型
解构赋值
=>函数
...操作符
类
ES7新特性
Array.prototype.includes
Exponentiation Operator(求幂运算)
ES8新特性
Object.ies
String padding(字符串填充)
函数参数列表和调⽤中的尾逗号(Trailing commas)
异步函数(Async Functions)
如何让Nodejs⽀持对应的ES
不同版本的Node.js对Babel有不同的⽀持,如若是Nodejs⽀持ES6语法,需要引⼊babel。因此要安装⼀些babel的依赖包,如babel-preset-es2015 / babel-core /babel-cli。ES6对应es2015,ES7对应es2016,ES8对应es2017,同时对应⽀持的node版本更⾼。
检测ES6
可以使⽤来检测当前Node.js对ES6的⽀持情况,全局安装es-checker
$ npm install -g es-checker
安装好之后,执⾏以下命令来查看Node.js对ES6的⽀持情况:
$ es-checker
可以从输出中查看当前版本Node.js(v7.7.4)对ES6的⽀持情况:
js assign$ es-checker
ECMAScript 6 Feature Detection (v1.4.1)
Variables
√ let and const
√ TDZ error for too-early access of let or const declarations
√ Redefinition of const declarations not allowed
√ destructuring assignments/declarations for arrays and objects
√ ... operator
Data Types
√ f loop
√ Map, Set, WeakMap, WeakSet
√ Symbol
√ Symbols cannot be implicitly coerced
Number
√ Octal (e.g. 0o1 ) and binary (e.g. 0b10 ) literal forms
√ Old octal literal invalid now (e.g. 01 )
√ Static functions added to Math (e.g. Math.hypot(), Math.acosh(), Math.imul() )
√ Static functions added to Number (Number.isNaN(), Number.isInteger() )
String
√ Methods added to String.prototype (String.prototype.includes(), peat() )
√ Unicode code-point escape form in string literals (e.g. \u{20BB7} )
√ Unicode code-point escape form in identifier names (e.g. var \u{20BB7} = 42; )
√ Unicode code-point escape form in regular expressions (e.g. var regexp = /\u{20BB7}/u; )
√ y flag for sticky regular expressions (e.g. /b/y )
√ Template String Literals
Function
√ arrow function
√ default function parameter values
√ destructuring for function parameters
√ Inferences for function name property for anonymous functions
× Tail-call optimization for function calls and recursion
Array
× Methods added to Array.prototype ([].fill(), [].find(), [].findIndex(), [].entries(), [].keys(), [].values() )
√ Static functions added to Array (Array.from(), Array.of() )
√ TypedArrays like Uint8Array, ArrayBuffer, Int8Array(), Int32Array(), Float64Array()
√ Some Array methods (e.g. Int8Array.prototype.slice(), Int8Array.prototype.join(), Int8Array.prototype.forEach() ) added to the TypedArray prototypes
√ Some Array statics (e.g. Uint32Array.from(), Uint32Array.of() ) added to the TypedArray constructors
Object
√ __proto__ in object literal definition sets [[Prototype]] link
√ Static functions added to Object (OwnPropertySymbols(), Object.assign() )
√ Object Literal Computed Property
√ Object Literal Property Shorthands
√ Proxies
√ Reflect
Generator and Promise
√ Generator function
√ Promises
Class
√ Class
√ super allowed in object methods
√ class ABC extends Array { .. }
Module
× Module export command
× Module import command
=========================================
Passes 38 feature Detections
Your runtime supports 90% of ECMAScript 6
=========================================
View Code
添加es6⽀持
全局安abel-cli,项⽬安装 babel-preset-es2015:
npm install babel-cli -g
npm install babel-preset-es2015 --save
安装完之后,还需要添加⼀个名为.babelrc的配置⽂件。⽅便babel-cli使⽤babel-preset-es2015。⽂件内容如下:
{
"presets": ["es2015"],
"plugins": [
"add-module-exports"
]
}
或者在项⽬⼊⼝⽂件(如app.js)引⽤下babel:
require('babel-register')({
presets: ['es2015']
});
如此,再也不会报如下的错误:
import a from './config';
^^^^^^
SyntaxError: Unexpected token import
并且也会⽀持ES6的新特性。上述是描述node如何⽀持ES6的,⽀持ES8是类似的,preset指定 "presets": ["es2017"]即可。
下⾯进⼊正题,到底ES6~8有哪些实⽤的新特性呢
ES6常⽤新特性
let && const
let 命令也⽤于变量声明,但是作⽤域为局部
{
let a = 10;
var b = 1;
}
在函数外部可以获取到b,获取不到a,因此例如for循环计数器就适合使⽤let。
const⽤于声明⼀个常量,设定后值不会再改变
const PI = 3.1415;
PI // 3.1415
PI = 3; //TypeError: Assignment to constant variable.
iterable类型
为了统⼀集合类型,ES6标准引⼊了新的iterable类型,Array、Map和Set都属于iterable类型,具有iterable类型的集合可以通过新的for … of循环来遍历。var a = ['A', 'B', 'C'];
var s = new Set(['A', 'B', 'C']);
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
for (var x of a) { // 遍历Array
alert(x);
}
for (var x of s) { // 遍历Set
alert(x);
}
for (var x of m) { // 遍历Map
alert(x[0] + '=' + x[1]);
}
Map相关操作如下, Set同理:
var m = new Map(); // 空Map
m.set('Adam', 67); // 添加新的key-value
m.set('Bob', 59);
m.has('Adam'); // 是否存在key 'Adam': true
<('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
<('Adam'); // undefined
解构赋值
ES6 允许按照⼀定模式,从数组和对象中提取值,对变量进⾏赋值,这被称为解构(Destructuring)。
例如数组:
let [a, b, c] = [1, 2, 3];
//等同于
let a = 1;
let b = 2;
let c = 3;
这真的让代码看起来更优美,有种python赋值的既视感。
对象的解构赋值:获取对象的多个属性并且使⽤⼀条语句将它们赋给多个变量。
var {
StyleSheet,
Text,
View
} = React;
等同于
var StyleSheet = React.StyleSheet;
var Text = React.Text;
var View = React.Text;
箭头函数
ES6中新增箭头操作符⽤于简化函数的写法,操作符左边为参数,右边为具体操作和返回值。
var sum = (num1, num2) => { return num1 + num2; }
//等同于
var sum = function(num1, num2) {
return num1 + num2;
};
箭头函数还修复了this的指向,使其永远指向词法作⽤域:
var obj = {
birth: 1990,
getAge: function () {
var b = this.birth; // 1990
var fn = () => new Date().getFullYear() - this.birth; // this指向obj对象
return fn();
}
};
...操作符
这个的引⼊⼏乎不会⽤到extend这个函数来。通过它可以将数组作为参数直接传⼊函数:
var people=['Wayou','John','Sherlock'];
function sayHello(people1,people2,people3){
console.log(`Hello ${people1},${people2},${people3}`);
}
//改写为
sayHello(...people);//输出:Hello Wayou,John,Sherlock
在函数定义时可以通过…rest获取定义参数外的所有参数(类似C#中的参数数组,可以有任意多个参数):
function foo(a, b, ...rest) {
console.log('a = ' + a);
console.log('b = ' + b);
console.log(rest);
}
foo(1, 2, 3, 4, 5);
// 结果:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]
这个真是完美!关于更多...的说明参考
类
ES6提供了更接近传统语⾔的写法,引⼊了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类,与多数传统语⾔类似。
//定义类
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
ES7新特性
Array.prototype.includes
Array.prototype.includes⽤法都容易和简单。它是⼀个替代indexOf,开发⼈员⽤来检查数组中是否存在值,indexOf是⼀种尴尬的使⽤,因为它返回⼀个元素在数组中的位置或者-1当这样的元素不能被到的情况下。所以它返回⼀个数字,⽽不是⼀个布尔值。开发⼈员需要实施额外的检查。在ES6,要检查是否存在值你需要做⼀些如下图所⽰⼩技巧,因为他们没有匹配到值,Array.prototype.indexOf返回-1变成了true(转换成true),但是当匹配的元素为0位置时候,该数组包含元素,却变成了false。
let arr = ['react', 'angular', 'vue']
// WRONG
if (arr.indexOf('react')) { // 0 -> evaluates to false, definitely as we expected
console.log('Can use React') // this line would never be executed
}
// Correct
if (arr.indexOf('react') !== -1) {
console.log('Can use React')
}
或者使⽤⼀点点hack 位运算符~使代码更加紧凑⼀些,因为~(位异或)对任何数字相当于-(a + 1):
let arr = ['react', 'angular', 'vue']
// Correct
if (~arr.indexOf('react')) {
console.log('Can use React')
}
在ES7中使⽤includes代码如下:
let arr = ['react', 'angular', 'vue']
// Correct
if (arr.includes('react')) {
console.log('Can use React')
}
还能在字符串中使⽤includes:
let str = 'React Quickly'
/
/ Correct
if (LowerCase().includes('react')) { // true
console.log('Found "react"')
}
除了增强了可读性语义化,实际上给开发者返回布尔值,⽽不是匹配的位置。
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)
总⽽⾔之,includes在⼀个数组或者列表中检查是否存在⼀个值,给任何开发⼈员带来简单性。
Exponentiation Operator(求幂运算)
求幂运算⼤多数是做⼀些数学计算,对于3D,VR,SVG还有数据可视化⾮常有⽤。在ES6或者早些版本,不得不创建⼀个循环,创建⼀个递归函数或者使⽤Math.pow,如果忘记了什么是指数,当你有相同数字(基数)⾃相相乘多次(指数)。例如,7的3次⽅是7*7*7
所以在ES6/2015ES,你能使⽤Math.pow创建⼀个短的递归箭头函数:
calculateExponent = (base, exponent) => base*((--exponent>1)?calculateExponent(base, exponent):base)
console.log(calculateExponent(7,12) === Math.pow(7,12)) // true
console.log(calculateExponent(2,7) === Math.pow(2,7)) // true
现在在ES7 /ES2016,以数学向导的开发者可以使⽤更短的语法:
let a = 7 ** 12
let b = 2 ** 7
console.log(a === Math.pow(7,12)) // true
console.log(b === Math.pow(2,7)) // true
开发者还可以操作结果:
let a = 7
a **= 12
let b = 2
b **= 7
console.log(a === Math.pow(7,12)) // true
console.log(b === Math.pow(2,7)) // true
许多ES新特性是从其他语⾔(CoffeeScript,Ruby,python等)模仿⽽来的
ES8新特性
Object.ies
Object.values和ies是在ES2017规格中,它和Object.keys类似,返回数组类型,其序号和Object.keys序号对应。类似python中的dict.iteritems()。
Object.ies和Object.keys各⾃项返回是数组,相对应包括key,value或者可枚举特定对象property/attribute
在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])
}
Object.values返回对象⾃⾝可以迭代属性值(values)为数组类型。我们最好使⽤Array.prototype.forEach迭代它,结合ES6的箭头函数隐形返回值:
let obj = {a: 1, b: 2, c: 3}
Object.values(obj).forEach(value=>console.log(value)) // 1, 2, 3
或者实⽤for/of:
let obj = {a: 1, b: 2, c: 3}
for (let value of Object.values(obj)) {
console.log(value)
}
// 1, 2, 3
·ies·,在另⼀⽅⾯,将会返回对象⾃⾝可迭代属性key-value对数组(作为⼀个数组),他们(key-value)分别以数组存放数组中:
let obj = {a: 1, b: 2, c: 3}
JSON.ies(obj))
"[["a",1],["b",2],["c",3]]"
可以使⽤ES6/ES2015解构,从这嵌套数组中分别声明key和value
let obj = {a: 1, b: 2, c: 3}
console.log(`${key} is ${value}`)
})
// a is 1, b is 2, c is 3
同样使⽤ES6for/of(毕竟全部都是数组)遍历ies返回来的结果值:
let obj = {a: 1, b: 2, c: 3}
for (let [key, value] ies(obj)) {
console.log(`${key} is ${value}`)
}
// a is 1, b is 2, c is 3
现在从对象中提取values和key-value pairs 变得⾮常容易了。Object.values和ies这种⽅式不想之前Object.keys(⾃⾝属性key+顺序相同)结合for/of(ES6)⼀起,我们不仅仅可以提取他们还可以迭代他们。
String padding(字符串填充)
String.prototype.padStart和String.prototype.padEnd在javascript字符操作是⼀个不错的体验,帮助避免依赖⽽外的库。
padStart()在开始部位填充,返回⼀个给出长度的字符串,填充物给定字符串,把字符串填充到期望的长度。从字符串的左边开始(⾄少⼤部分西⽅语⾔),⼀个经典例⼦是使⽤空格创建列:
console.log('react'.padStart(10).length) // " react" is 10
console.log('backbone'.padStart(10).length) // " backbone" is 10
它对于财务⽅⾯⾮常有⽤:
console.log('0.00'.padStart(20))
console.log('10,000.00'.padStart(20))
console.log('250,000.00'.padStart(20))
如果是为会计做账之类的,这个很实⽤,帐做的很整齐
0.00
10,000.00
250,000.00
第⼆个参数,让我们放⼀些其他的填充字符替代空字符串,⼀个字符串填充:
console.log('react'.padStart(10, '_')) // "_____react"
console.log('backbone'.padStart(10, '*')) // "**backbone"
padEnd顾名思义就是从字符串的尾端右边开始填充。第⼆个参数,你能实际上⽤⼀个任何长度的字符串。例如:
console.log('react'.padEnd(10, ':-)')) // "react:-):-" is 10
console.log('backbone'.padEnd(10, '*')) // "backbone**" is 10
再赏⼏个例⼦作为总结:
// String.prototype.padStart(targetLength [, padString])
'hello'.padStart(10); // ' hello'
'hello'.padStart(10, '0'); // '00000hello'
'hello'.padStart(); // 'hello'
'hello'.padStart(6, '123'); // '1hello'
'hello'.padStart(3); // 'hello'
'hello'.padStart(3, '123'); // 'hello';
// String.prototype.padEnd(targetLength [, padString])
'hello'.padEnd(10); // 'hello '
'hello'.padEnd(10, '0'); // 'hello00000'
'hello'.padEnd(); // 'hello'
'hello'.padEnd(6, '123'); // 'hello1'
'hello'.padEnd(3); // 'hello'
'hello'.padEnd(3, '123'); // 'hello';
这新的OwnPropertyDescriptors返回对象obj所有⾃⾝属性描述。这是⼀个多参数版本的将会返回obj中propName属性的⼀个单独描述。
在我们⽇常不可变编程(immutable programming)时代中,有了这个⽅法很⽅便(记住,Javascript中对象是引⽤传递)在ES5中,开发者要使⽤Object.assign()来拷贝对象, Object.assign()分配属性只有copy和定义新的属性。当我们使⽤更加复杂对象和类原型,这可能会出问题。
)
或者可以合并两个对象target和source如下:
Object.defineProperties(
target,
)
以上是OwnPropertyDesciptors⽤法。但是什么是描述符(descriptor)呢?就是⼀个对象的描述。
这⾥有两种描述符号类型:
1.数据描述符(Data descriptor)
2.存取器描述符(Accessor descriptor)
存取描述符有必须属性:get 或者set或者get和set两个就是如你所想的getter和setter函数,然后存取描述符还有可选属性configurable和enumerable
let azatsBooks = {
books: ['React Quickly'],
get latest () {
let numberOfBooks = this.books.length
if (numberOfBooks == 0) return undefined
return this.books[numberOfBooks - 1]
}
}
这个例⼦数据描述符books由OwnPropertyDescriptor(azatsBooks, 'books')产⽣结果如下:
Object
configurable: true
enumerable: true
value: Array[1]
writable: true
__proto__: Object
同样的,OwnPropertyDescriptor(azatsBooks, 'latest')将会展现latest的描述符,这个latest(get)存取器描述符展现如下:
Object
configurable: truee
numerable: true
get: latest()
set: undefined
__proto__: Object
现在我们调⽤新⽅法获取所有的描述符:
console.OwnPropertyDescriptors(azatsBooks))
它会给出这个对象两个描述符books和latest:
Object
books: Object
configurable: true
enumerable: true
value: Array[1]
writable: true
__proto__: Object
latest: Object
configurable: true
enumerable: true
get: latest()
set: undefined
__proto__: Object
__proto__: Object
函数参数列表和调⽤中的尾逗号(Trailing commas)
尾逗号在函数定义中只是⼀个纯粹语法变化,在ES5中,将会⾮法语法,在函数参数后⾯应该是没有逗号的:
var f = function(a,
b,
c,
d) { // NO COMMA!
// ...
console.log(d)
}
f(1,2,3,'this')
在ES8中,这种尾逗号是没有问题的:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论