ES6、ES7、ES8學(xué)習(xí)指南(復(fù)習(xí)下)
作者:CrazyCodeBoy?
鏈接:https://www.jianshu.com/p/1ae1dd4cdaa7

概述
ES全稱ECMAScript,ECMAScript是ECMA制定的標(biāo)準(zhǔn)化腳本語言。目前JavaScript使用的ECMAScript版本為ECMAScript-262。
ECMAScript 標(biāo)準(zhǔn)建立在一些原有的技術(shù)上,最為著名的是 JavaScript (網(wǎng)景) 和 JScript (微軟)。它最初由網(wǎng)景的 Brendan Eich 發(fā)明,第一次出現(xiàn)是在網(wǎng)景的 Navigator 2.0 瀏覽器上。Netscape 2.0 以及微軟 Internet Explorer 3.0 后序的所有瀏覽器上都有它的身影。

了解這些特性,不僅能使我們的編碼更加的符合規(guī)范,而且能提高我們Coding的效率。
ES6的特性
ES6的特性比較多,在 ES5 發(fā)布近 6 年(2009-11 至 2015-6)之后才將其標(biāo)準(zhǔn)化。兩個(gè)發(fā)布版本之間時(shí)間跨度很大,所以ES6中的特性比較多。
在這里列舉幾個(gè)常用的:
類 模塊化 箭頭函數(shù) 函數(shù)參數(shù)默認(rèn)值 模板字符串 解構(gòu)賦值 延展操作符 對(duì)象屬性簡寫 Promise Let與Const
1.類(class)
對(duì)熟悉Java,object-c,c#等純面向?qū)ο笳Z言的開發(fā)者來說,都會(huì)對(duì)class有一種特殊的情懷。ES6 引入了class(類),讓JavaScript的面向?qū)ο缶幊套兊酶雍唵魏鸵子诶斫狻?/p>
?class?Animal?{
????//?構(gòu)造函數(shù),實(shí)例化的時(shí)候?qū)?huì)被調(diào)用,如果不指定,那么會(huì)有一個(gè)不帶參數(shù)的默認(rèn)構(gòu)造函數(shù).
????constructor(name,color)?{
??????this.name?=?name;
??????this.color?=?color;
????}
????//?toString?是原型對(duì)象上的屬性
????toString()?{
??????console.log('name:'?+?this.name?+?',color:'?+?this.color);
????}
??}
?var?animal?=?new?Animal('dog','white');//實(shí)例化Animal
?animal.toString();
?console.log(animal.hasOwnProperty('name'));?//true
?console.log(animal.hasOwnProperty('toString'));?//?false
?console.log(animal.__proto__.hasOwnProperty('toString'));?//?true
?class?Cat?extends?Animal?{
??constructor(action)?{
????//?子類必須要在constructor中指定super?函數(shù),否則在新建實(shí)例的時(shí)候會(huì)報(bào)錯(cuò).
????//?如果沒有置頂consructor,默認(rèn)帶super函數(shù)的constructor將會(huì)被添加、
????super('cat','white');
????this.action?=?action;
??}
??toString()?{
????console.log(super.toString());
??}
?}
?var?cat?=?new?Cat('catch')
?cat.toString();
?//?實(shí)例cat 是 Cat 和 Animal 的實(shí)例,和Es5完全一致。
?console.log(cat?instanceof?Cat);?//?true
?console.log(cat?instanceof?Animal);?//?true?
2.模塊化(Module)
ES5不支持原生的模塊化,在ES6中模塊作為重要的組成部分被添加進(jìn)來。模塊的功能主要由 export 和 import 組成。每一個(gè)模塊都有自己單獨(dú)的作用域,模塊之間的相互調(diào)用關(guān)系是通過 export 來規(guī)定模塊對(duì)外暴露的接口,通過import來引用其它模塊提供的接口。同時(shí)還為模塊創(chuàng)造了命名空間,防止函數(shù)的命名沖突。
導(dǎo)出(export)
ES6允許在一個(gè)模塊中使用export來導(dǎo)出多個(gè)變量或函數(shù)。
導(dǎo)出變量
//test.js
export?var?name?=?'Rainbow'?
心得:ES6不僅支持變量的導(dǎo)出,也支持常量的導(dǎo)出。
export const sqrt = Math.sqrt;//導(dǎo)出常量
ES6將一個(gè)文件視為一個(gè)模塊,上面的模塊通過 export 向外輸出了一個(gè)變量。一個(gè)模塊也可以同時(shí)往外面輸出多個(gè)變量。
?//test.js
?var?name?=?'Rainbow';
?var?age?=?'24';
?export?{name,?age};?
導(dǎo)出函數(shù)
//?myModule.js
export?function?myModule(someArg)?{
??return?someArg;
}?
導(dǎo)入(import)
定義好模塊的輸出以后就可以在另外一個(gè)模塊通過import引用。
import?{myModule}?from?'myModule';//?main.js
import?{name,age}?from?'test';//?test.js?
心得:一條import 語句可以同時(shí)導(dǎo)入默認(rèn)函數(shù)和其它變量。
import defaultMethod, { otherMethod } from 'xxx.js';
3.箭頭(Arrow)函數(shù)
這是ES6中最令人激動(dòng)的特性之一。=>不只是關(guān)鍵字function的簡寫,它還帶來了其它好處。箭頭函數(shù)與包圍它的代碼共享同一個(gè)this,能幫你很好的解決this的指向問題。有經(jīng)驗(yàn)的JavaScript開發(fā)者都熟悉諸如var self = this;或var that = this這種引用外圍this的模式。但借助=>,就不需要這種模式了。
箭頭函數(shù)的結(jié)構(gòu)
箭頭函數(shù)的箭頭=>之前是一個(gè)空括號(hào)、單個(gè)的參數(shù)名、或用括號(hào)括起的多個(gè)參數(shù)名,而箭頭之后可以是一個(gè)表達(dá)式(作為函數(shù)的返回值),或者是用花括號(hào)括起的函數(shù)體(需要自行通過return來返回值,否則返回的是undefined)。
//?箭頭函數(shù)的例子
()=>1
v=>v+1
(a,b)=>a+b
()=>{
????alert("foo");
}
e=>{
????if?(e?==?0){
????????return?0;
????}
????return?1000/e;
}?
心得:不論是箭頭函數(shù)還是bind,每次被執(zhí)行都返回的是一個(gè)新的函數(shù)引用,因此如果你還需要函數(shù)的引用去做一些別的事情(譬如卸載監(jiān)聽器),那么你必須自己保存這個(gè)引用。
卸載監(jiān)聽器時(shí)的陷阱
錯(cuò)誤的做法
class?PauseMenu?extends?React.Component{
????componentWillMount(){
????????AppStateIOS.addEventListener('change',?this.onAppPaused.bind(this));
????}
????componentWillUnmount(){
????????AppStateIOS.removeEventListener('change',?this.onAppPaused.bind(this));
????}
????onAppPaused(event){
????}
}?
正確的做法
class?PauseMenu?extends?React.Component{
????constructor(props){
????????super(props);
????????this._onAppPaused?=?this.onAppPaused.bind(this);
????}
????componentWillMount(){
????????AppStateIOS.addEventListener('change',?this._onAppPaused);
????}
????componentWillUnmount(){
????????AppStateIOS.removeEventListener('change',?this._onAppPaused);
????}
????onAppPaused(event){
????}
}?
除上述的做法外,我們還可以這樣做:
class?PauseMenu?extends?React.Component{
????componentWillMount(){
????????AppStateIOS.addEventListener('change',?this.onAppPaused);
????}
????componentWillUnmount(){
????????AppStateIOS.removeEventListener('change',?this.onAppPaused);
????}
????onAppPaused?=?(event)?=>?{
????????//把函數(shù)直接作為一個(gè)arrow?function的屬性來定義,初始化的時(shí)候就綁定好了this指針
????}
}?
需要注意的是:不論是bind還是箭頭函數(shù),每次被執(zhí)行都返回的是一個(gè)新的函數(shù)引用,因此如果你還需要函數(shù)的引用去做一些別的事情(譬如卸載監(jiān)聽器),那么你必須自己保存這個(gè)引用。
4.函數(shù)參數(shù)默認(rèn)值
ES6支持在定義函數(shù)的時(shí)候?yàn)槠湓O(shè)置默認(rèn)值:
function?foo(height?=?50,?color?=?'red')
{
????//?...
}?
不使用默認(rèn)值:
function?foo(height,?color)
{
????var?height?=?height?||?50;
????var?color?=?color?||?'red';
????//...
}?
這樣寫一般沒問題,但當(dāng)參數(shù)的布爾值為false時(shí),就會(huì)有問題了。比如,我們這樣調(diào)用foo函數(shù):
foo(0,?"")?
因?yàn)?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(0, 150, 136);">0的布爾值為false,這樣height的取值將是50。同理color的取值為‘red’。
所以說,函數(shù)參數(shù)默認(rèn)值不僅能是代碼變得更加簡潔而且能規(guī)避一些問題。
5.模板字符串
ES6支持模板字符串,使得字符串的拼接更加的簡潔、直觀。
不使用模板字符串:
var?name?=?'Your?name?is?'?+?first?+?'?'?+?last?+?'.'?
使用模板字符串:
var?name?=?`Your?name?is?${first}?${last}.`?
在ES6中通過${}就可以完成字符串的拼接,只需要將變量放在大括號(hào)之中。
6.解構(gòu)賦值
解構(gòu)賦值語法是JavaScript的一種表達(dá)式,可以方便的從數(shù)組或者對(duì)象中快速提取值賦給定義的變量。
獲取數(shù)組中的值
從數(shù)組中獲取值并賦值到變量中,變量的順序與數(shù)組中對(duì)象順序?qū)?yīng)。
var?foo?=?["one",?"two",?"three",?"four"];
var?[one,?two,?three]?=?foo;
console.log(one);?//?"one"
console.log(two);?//?"two"
console.log(three);?//?"three"
//如果你要忽略某些值,你可以按照下面的寫法獲取你想要的值
var?[first,?,?,?last]?=?foo;
console.log(first);?//?"one"
console.log(last);?//?"four"
//你也可以這樣寫
var?a,?b;?//先聲明變量
[a,?b]?=?[1,?2];
console.log(a);?//?1
console.log(b);?//?2?
如果沒有從數(shù)組中的獲取到值,你可以為變量設(shè)置一個(gè)默認(rèn)值。
var?a,?b;
[a=5,?b=7]?=?[1];
console.log(a);?//?1
console.log(b);?//?7?
通過解構(gòu)賦值可以方便的交換兩個(gè)變量的值。
var?a?=?1;
var?b?=?3;
[a,?b]?=?[b,?a];
console.log(a);?//?3
console.log(b);?//?1?
獲取對(duì)象中的值
const?student?=?{
??name:'Ming',
??age:'18',
??city:'Shanghai'??
};
const?{name,age,city}?=?student;
console.log(name);?//?"Ming"
console.log(age);?//?"18"
console.log(city);?//?"Shanghai"?
7.延展操作符(Spread operator)
延展操作符...可以在函數(shù)調(diào)用/數(shù)組構(gòu)造時(shí), 將數(shù)組表達(dá)式或者string在語法層面展開;還可以在構(gòu)造對(duì)象時(shí), 將對(duì)象表達(dá)式按key-value的方式展開。
語法
函數(shù)調(diào)用:
myFunction(...iterableObj);?
數(shù)組構(gòu)造或字符串:
[...iterableObj,?'4',?...'hello',?6];?
構(gòu)造對(duì)象時(shí),進(jìn)行克隆或者屬性拷貝(ECMAScript 2018規(guī)范新增特性):
let?objClone?=?{?...obj?};?
應(yīng)用場景
在函數(shù)調(diào)用時(shí)使用延展操作符
function?sum(x,?y,?z)?{
??return?x?+?y?+?z;
}
const?numbers?=?[1,?2,?3];
//不使用延展操作符
console.log(sum.apply(null,?numbers));
//使用延展操作符
console.log(sum(...numbers));//?6?
構(gòu)造數(shù)組
沒有展開語法的時(shí)候,只能組合使用 push,splice,concat 等方法,來將已有數(shù)組元素變成新數(shù)組的一部分。有了展開語法, 構(gòu)造新數(shù)組會(huì)變得更簡單、更優(yōu)雅:
const?stuendts?=?['Jine','Tom'];?
const?persons?=?['Tony',...?stuendts,'Aaron','Anna'];
conslog.log(persions)//?["Tony",?"Jine",?"Tom",?"Aaron",?"Anna"]?
和參數(shù)列表的展開類似, ... 在構(gòu)造字?jǐn)?shù)組時(shí), 可以在任意位置多次使用。
數(shù)組拷貝
var?arr?=?[1,?2,?3];
var?arr2?=?[...arr];?//?等同于?arr.slice()
arr2.push(4);?
console.log(arr2)//[1,?2,?3,?4]?
展開語法和 Object.assign() 行為一致, 執(zhí)行的都是淺拷貝(只遍歷一層)。
連接多個(gè)數(shù)組
var?arr1?=?[0,?1,?2];
var?arr2?=?[3,?4,?5];
var?arr3?=?[...arr1,?...arr2];//?將?arr2?中所有元素附加到?arr1?后面并返回
//等同于
var?arr4?=?arr1.concat(arr2);?
在ECMAScript 2018中延展操作符增加了對(duì)對(duì)象的支持
var?obj1?=?{?foo:?'bar',?x:?42?};
var?obj2?=?{?foo:?'baz',?y:?13?};
var?clonedObj?=?{?...obj1?};
//?克隆后的對(duì)象:?{?foo:?"bar",?x:?42?}
var?mergedObj?=?{?...obj1,?...obj2?};
//?合并后的對(duì)象:?{?foo:?"baz",?x:?42,?y:?13?}?
在React中的應(yīng)用
通常我們在封裝一個(gè)組件時(shí),會(huì)對(duì)外公開一些 props 用于實(shí)現(xiàn)功能。大部分情況下在外部使用都應(yīng)顯示的傳遞 props 。但是當(dāng)傳遞大量的props時(shí),會(huì)非常繁瑣,這時(shí)我們可以使用 ...(延展操作符,用于取出參數(shù)對(duì)象的所有可遍歷屬性) 來進(jìn)行傳遞。
一般情況下我們應(yīng)該這樣寫
<CustomComponent?name?='Jine'?age?={21}?/>?
使用 ... ,等同于上面的寫法
const?params?=?{
????????name:?'Jine',
????????age:?21
????}
params}?/>?
配合解構(gòu)賦值避免傳入一些不需要的參數(shù)
var params = {
name: '123',
title: '456',
type: 'aaa'
}
var { type, ...other } = params;
//等同于
8.對(duì)象屬性簡寫
在ES6中允許我們在設(shè)置一個(gè)對(duì)象的屬性的時(shí)候不指定屬性名。
不使用ES6
const?name='Ming',age='18',city='Shanghai';
????????
const?student?=?{
????name:name,
????age:age,
????city:city
};
console.log(student);//{name:?"Ming",?age:?"18",?city:?"Shanghai"}?
對(duì)象中必須包含屬性和值,顯得非常冗余。
使用ES6
const?name='Ming',age='18',city='Shanghai';
????????
const?student?=?{
????name,
????age,
????city
};
console.log(student);//{name:?"Ming",?age:?"18",?city:?"Shanghai"}?
對(duì)象中直接寫變量,非常簡潔。
9.Promise
Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案callback更加的優(yōu)雅。它最早由社區(qū)提出和實(shí)現(xiàn)的,ES6 將其寫進(jìn)了語言標(biāo)準(zhǔn),統(tǒng)一了用法,原生提供了Promise對(duì)象。
不使用ES6
嵌套兩個(gè)setTimeout回調(diào)函數(shù):
setTimeout(function()
{
????console.log('Hello');?//?1秒后輸出"Hello"
????setTimeout(function()
????{
????????console.log('Hi');?//?2秒后輸出"Hi"
????},?1000);
},?1000);?
使用ES6
var?waitSecond?=?new?Promise(function(resolve,?reject)
{
????setTimeout(resolve,?1000);
});
waitSecond
????.then(function()
????{
????????console.log("Hello");?//?1秒后輸出"Hello"
????????return?waitSecond;
????})
????.then(function()
????{
????????console.log("Hi");?//?2秒后輸出"Hi"
????});?
上面的的代碼使用兩個(gè)then來進(jìn)行異步編程串行化,避免了回調(diào)地獄:
10.支持let與const
在之前JS是沒有塊級(jí)作用域的,const與let填補(bǔ)了這方便的空白,const與let都是塊級(jí)作用域。
使用var定義的變量為函數(shù)級(jí)作用域:
{
??var?a?=?10;
}
console.log(a);?//?輸出10?
使用let與const定義的變量為塊級(jí)作用域:
{
??let?a?=?10;
}
console.log(a);?//-1?or?Error“ReferenceError:?a?is?not?defined”?
ES7的特性
在ES6之后,ES的發(fā)布頻率更加頻繁,基本每年一次,所以自ES6之后,每個(gè)新版本的特性的數(shù)量就比較少。
includes() 指數(shù)操作符
1. Array.prototype.includes()
includes() 函數(shù)用來判斷一個(gè)數(shù)組是否包含一個(gè)指定的值,如果包含則返回 true,否則返回false。
includes 函數(shù)與 indexOf 函數(shù)很相似,下面兩個(gè)表達(dá)式是等價(jià)的:
arr.includes(x)
arr.indexOf(x) >= 0
接下來我們來判斷數(shù)字中是否包含某個(gè)元素:
在ES7之前的做法
使用indexOf()驗(yàn)證數(shù)組中是否存在某個(gè)元素,這時(shí)需要根據(jù)返回值是否為-1來判斷:
let?arr?=?['react',?'angular',?'vue'];
if?(arr.indexOf('react')?!==?-1)
{
????console.log('react存在');
}?
使用ES7的includes()
使用includes()驗(yàn)證數(shù)組中是否存在某個(gè)元素,這樣更加直觀簡單:
let?arr?=?['react',?'angular',?'vue'];
if?(arr.includes('react'))
{
????console.log('react存在');
}?
2.指數(shù)操作符
在ES7中引入了指數(shù)運(yùn)算符**,**具有與Math.pow(..)等效的計(jì)算結(jié)果。
不使用指數(shù)操作符
使用自定義的遞歸函數(shù)calculateExponent或者M(jìn)ath.pow()進(jìn)行指數(shù)運(yùn)算:
function?calculateExponent(base,?exponent)
{
????if?(exponent?===?1)
????{
????????return?base;
????}
????else
????{
????????return?base?*?calculateExponent(base,?exponent?-?1);
????}
}
console.log(calculateExponent(2,?10));?//?輸出1024
console.log(Math.pow(2,?10));?//?輸出1024?
使用指數(shù)操作符
使用指數(shù)運(yùn)算符**,就像+、-等操作符一樣:
console.log(2**10);//?輸出1024?
ES8的特性
async/await Object.values() Object.entries() String padding 函數(shù)參數(shù)列表結(jié)尾允許逗號(hào) Object.getOwnPropertyDescriptors()
瀏覽器兼容性
1.async/await
在ES8中加入了對(duì)async/await的支持,也就我們所說的異步函數(shù),這是一個(gè)很實(shí)用的功能。async/await將我們從頭痛的回調(diào)地獄中解脫出來了,使整個(gè)代碼看起來很簡潔。
使用
async/await與不使用async/await的差別:
login(userName)?{
????return?new?Promise((resolve,?reject)?=>?{
????????setTimeout(()?=>?{
????????????resolve('1001');
????????},?600);
????});
}
getData(userId)?{
????return?new?Promise((resolve,?reject)?=>?{
????????setTimeout(()?=>?{
????????????if?(userId?===?'1001')?{
????????????????resolve('Success');
????????????}?else?{
????????????????reject('Fail');
????????????}
????????},?600);
????});
}
//?不使用async/await?ES7
doLogin(userName)?{
????this.login(userName)
????????.then(this.getData)
????????.then(result?=>?{
????????????console.log(result)
????????})
}
//?使用async/await?ES8
async?doLogin2(userName)?{
????const?userId=await?this.login(userName);
????const?result=await?this.getData(userId);
}
this.doLogin()//?Success
this.doLogin2()//?Success?
async/await的幾種應(yīng)用場景
接下來我們來看一下async/await的幾種應(yīng)用場景。
獲取異步函數(shù)的返回值
異步函數(shù)本身會(huì)返回一個(gè)Promise,所以我們可以通過then來獲取異步函數(shù)的返回值。
async?function?charCountAdd(data1,?data2)?{
????const?d1=await?charCount(data1);
????const?d2=await?charCount(data2);
????return?d1+d2;
}
charCountAdd('Hello','Hi').then(console.log);//通過then獲取異步函數(shù)的返回值。
function?charCount(data)?{
????return?new?Promise((resolve,?reject)?=>?{
????????setTimeout(()?=>?{
????????????resolve(data.length);
????????},?1000);
????});
}?
async/await在并發(fā)場景中的應(yīng)用
對(duì)于上述的例子,我們調(diào)用await兩次,每次都是等待1秒一共是2秒,效率比較低,而且兩次await的調(diào)用并沒有依賴關(guān)系,那能不能讓其并發(fā)執(zhí)行呢,答案是可以的,接下來我們通過Promise.all來實(shí)現(xiàn)await的并發(fā)調(diào)用。
async?function?charCountAdd(data1,?data2)?{
????const?[d1,d2]=await?Promise.all([charCount(data1),charCount(data2)]);
????return?d1+d2;
}
charCountAdd('Hello','Hi').then(console.log);
function?charCount(data)?{
????return?new?Promise((resolve,?reject)?=>?{
????????setTimeout(()?=>?{
????????????resolve(data.length);
????????},?1000);
????});
}?
通過上述代碼我們實(shí)現(xiàn)了兩次charCount的并發(fā)調(diào)用,Promise.all接受的是一個(gè)數(shù)組,它可以將數(shù)組中的promise對(duì)象并發(fā)執(zhí)行;
async/await的幾種錯(cuò)誤處理方式
第一種:捕捉整個(gè)async/await函數(shù)的錯(cuò)誤
async?function?charCountAdd(data1,?data2)?{
????const?d1=await?charCount(data1);
????const?d2=await?charCount(data2);
????return?d1+d2;
}
charCountAdd('Hello','Hi')
????.then(console.log)
????.catch(console.log);//捕捉整個(gè)async/await函數(shù)的錯(cuò)誤
...?
這種方式可以捕捉整個(gè)charCountAdd運(yùn)行過程中出現(xiàn)的錯(cuò)誤,錯(cuò)誤可能是由charCountAdd本身產(chǎn)生的,也可能是由對(duì)data1的計(jì)算中或data2的計(jì)算中產(chǎn)生的。
第二種:捕捉單個(gè)的await表達(dá)式的錯(cuò)誤
async?function?charCountAdd(data1,?data2)?{
????const?d1=await?charCount(data1)
????????.catch(e=>console.log('d1?is?null'));
????const?d2=await?charCount(data2)
????????.catch(e=>console.log('d2?is?null'));
????return?d1+d2;
}
charCountAdd('Hello','Hi').then(console.log);?
通過這種方式可以捕捉每一個(gè)await表達(dá)式的錯(cuò)誤,如果既要捕捉每一個(gè)await表達(dá)式的錯(cuò)誤,又要捕捉整個(gè)charCountAdd函數(shù)的錯(cuò)誤,可以在調(diào)用charCountAdd的時(shí)候加個(gè)catch。
...
charCountAdd('Hello','Hi')
????.then(console.log)
????.catch(console.log);//捕捉整個(gè)async/await函數(shù)的錯(cuò)誤
...?
第三種:同時(shí)捕捉多個(gè)的await表達(dá)式的錯(cuò)誤
async?function?charCountAdd(data1,?data2)?{
????let?d1,d2;
????try?{
????????d1=await?charCount(data1);
????????d2=await?charCount(data2);
????}catch?(e){
????????console.log('d1?is?null');
????}
????return?d1+d2;
}
charCountAdd('Hello','Hi')
????.then(console.log);
function?charCount(data)?{
????return?new?Promise((resolve,?reject)?=>?{
????????setTimeout(()?=>?{
????????????resolve(data.length);
????????},?1000);
????});
}?
2.Object.values()
Object.values()是一個(gè)與Object.keys()類似的新函數(shù),但返回的是Object自身屬性的所有值,不包括繼承的值。
假設(shè)我們要遍歷如下對(duì)象obj的所有值:
const?obj?=?{a:?1,?b:?2,?c:?3};?
不使用Object.values() :ES7
const?vals=Object.keys(obj).map(key=>obj[key]);
console.log(vals);//[1,?2,?3]?
使用Object.values() :ES8
const?values=Object.values(obj1);
console.log(values);//[1,?2,?3]?
從上述代碼中可以看出Object.values()為我們省去了遍歷key,并根據(jù)這些key獲取value的步驟。
3.Object.entries
Object.entries()函數(shù)返回一個(gè)給定對(duì)象自身可枚舉屬性的鍵值對(duì)的數(shù)組。
接下來我們來遍歷上文中的obj對(duì)象的所有屬性的key和value:
不使用Object.entries() :ES7
Object.keys(obj).forEach(key=>{
????console.log('key:'+key+'?value:'+obj[key]);
})
//key:a?value:1
//key:b?value:2
//key:c?value:3?
使用Object.entries() :ES8
for(let?[key,value]?of?Object.entries(obj1)){
????console.log(`key:?${key}?value:${value}`)
}
//key:a?value:1
//key:b?value:2
//key:c?value:3?
4.String padding
在ES8中String新增了兩個(gè)實(shí)例函數(shù)String.prototype.padStart和String.prototype.padEnd,允許將空字符串或其他字符串添加到原始字符串的開頭或結(jié)尾。
String.padStart(targetLength,[padString])
targetLength:當(dāng)前字符串需要填充到的目標(biāo)長度。如果這個(gè)數(shù)值小于當(dāng)前字符串的長度,則返回當(dāng)前字符串本身。 padString:(可選)填充字符串。如果字符串太長,使填充后的字符串長度超過了目標(biāo)長度,則只保留最左側(cè)的部分,其他部分會(huì)被截?cái)?,此參?shù)的缺省值為 " "。
console.log('0.0'.padStart(4,'10'))?//10.0
console.log('0.0'.padStart(20))//????????????????0.00?
String.padEnd(targetLength,padString])
targetLength:當(dāng)前字符串需要填充到的目標(biāo)長度。如果這個(gè)數(shù)值小于當(dāng)前字符串的長度,則返回當(dāng)前字符串本身。 padString:(可選) 填充字符串。如果字符串太長,使填充后的字符串長度超過了目標(biāo)長度,則只保留最左側(cè)的部分,其他部分會(huì)被截?cái)?,此參?shù)的缺省值為 " ";
console.log('0.0'.padEnd(4,'0'))?//0.00?
console.log('0.0'.padEnd(10,'0'))//0.00000000?
4.函數(shù)參數(shù)列表結(jié)尾允許逗號(hào)
這是一個(gè)不痛不癢的更新,主要作用是方便使用git進(jìn)行多人協(xié)作開發(fā)時(shí)修改同一個(gè)函數(shù)減少不必要的行變更。
不使用ES8
//程序員A
var?f?=?function(a,
??b
???)?{?
??...
??}
//程序員B
var?f?=?function(a,
??b,???//變更行
??c???//變更行
???)?{?
??...
??}
//程序員C
var?f?=?function(a,
??b,
??c,???//變更行
??d???//變更行
???)?{?
??...
??}?
使用ES8
//程序員A
var?f?=?function(a,
??b,
???)?{?
??...
??}
//程序員B
var?f?=?function(a,
??b,
??c,???//變更行
???)?{?
??...
??}
//程序員C
var?f?=?function(a,
??b,
??c,
??d,???//變更行
???)?{?
??...
??}?
5.Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors()函數(shù)用來獲取一個(gè)對(duì)象的所有自身屬性的描述符,如果沒有任何自身屬性,則返回空對(duì)象。
函數(shù)原型:
Object.getOwnPropertyDescriptors(obj)?
返回obj對(duì)象的所有自身屬性的描述符,如果沒有任何自身屬性,則返回空對(duì)象。
const?obj2?=?{
????name:?'Jine',
????get?age()?{?return?'18'?}
};
Object.getOwnPropertyDescriptors(obj2)
//?{
//???age:?{
//?????configurable:?true,
//?????enumerable:?true,
//?????get:?function?age(){},?//the?getter?function
//?????set:?undefined
//???},
//???name:?{
//?????configurable:?true,
//?????enumerable:?true,
//??????value:"Jine",
//??????writable:true
//???}
//?}?
總結(jié)
技術(shù)更替的車輪一直在前進(jìn)中,JavaScript的規(guī)范和標(biāo)準(zhǔn)也在不斷的制定和完善。你會(huì)發(fā)現(xiàn)ECMAScript 新版的很多特性已經(jīng)是Typescript,瀏覽器或其他polyfills的一部分,就拿ES8的async/await來說,它是2017年6月被納入ECMAScript的,但我在2016年的時(shí)候就已經(jīng)開始使用這個(gè)特性了,這些特性通常由ECMAScript議員提交,然后會(huì)出現(xiàn)在在未來的某個(gè)ECMAScript版本中。
參考
MDN ECMAScript? 2016 ECMAScript? 2016 語言標(biāo)準(zhǔn) ECMAScript? 2017
??愛心三連擊
1.看到這里了就點(diǎn)個(gè)在看支持下吧,你的「點(diǎn)贊,在看」是我創(chuàng)作的動(dòng)力。
2.關(guān)注公眾號(hào)
程序員成長指北,回復(fù)「1」加入Node進(jìn)階交流群!「在這里有好多 Node 開發(fā)者,會(huì)討論 Node 知識(shí),互相學(xué)習(xí)」!3.也可添加微信【ikoala520】,一起成長。
“在看轉(zhuǎn)發(fā)”是最大的支持
