近期在複習ES6,針對ES6新的知識點,以問答形式整理一個全面知識和問題彙總。(全乾貨,適合對ES6有必定理解的同窗複習,以及ES6面試。)前端
答: ES6是新一代的JS語言標準,對分JS語言核心內容作了升級優化,規範了JS使用標準,新增了JS原生方法,使得JS使用更加規範,更加優雅,更適合大型應用的開發。java
答:babel是一個 ES6 轉碼器,能夠將 ES6 代碼轉爲 ES5 代碼,以便兼容那些還沒支持ES6的平臺。c++
答: 在ES6以前,聲明變量只能用var,var方式聲明變量實際上是很不合理的,準確的說,是由於ES5裏面沒有塊級做用域是很不合理的,甚至能夠說是一個語言層面的bug(這也是不少c++、java開發人員看不懂,也瞧不起JS語言的劣勢之一)。沒有塊級做用域回來帶不少難以理解的問題,好比for循環var變量泄露,變量覆蓋等問題。let 聲明的變量擁有本身的塊級做用域,且修復了var聲明變量帶來的變量提高問題。es6
ES6新增了字符串模板,在拼接大段字符串時,用反斜槓(`)取代以往的字符串相加的形式,能保留全部空格和換行,使得字符串拼接看起來更加直觀,更加優雅。面試
ES6在String原型上新增了includes()方法,用於取代傳統的只能用indexOf查找包含字符的方法(indexOf返回-1表示沒查到不如includes方法返回false更明確,語義更清晰), 此外還新增了startsWith(), endsWith(), padStart(),padEnd(),repeat()等方法,可方便的用於查找,補全字符串。編程
a. 數組解構賦值。ES6能夠直接以let [a,b,c] = [1,2,3]
形式進行變量賦值,在聲明較多變量時,不用再寫不少let(var),且映射關係清晰,且支持賦默認值。數組
b. 擴展運算符。ES6新增的擴展運算符(...)(重要),能夠輕鬆的實現數組和鬆散序列的相互轉化,能夠取代arguments對象和apply方法,輕鬆獲取未知參數個數狀況下的參數集合。(尤爲是在ES5中,arguments並非一個真正的數組,而是一個類數組的對象,可是擴展運算符的逆運算卻能夠返回一個真正的數組)。擴展運算符還能夠輕鬆方便的實現數組的複製和解構賦值(let a = [2,3,4]; let b = [...a]
)。瀏覽器
ES6在Array原型上新增了find()方法,用於取代傳統的只能用indexOf查找包含數組項目的方法,且修復了indexOf查找不到NaN的bug([NaN].indexOf(NaN) === -1
).此外還新增了copyWithin(), includes(), fill(),flat()等方法,可方便的用於字符串的查找,補全,轉換等。babel
ES6在Number原型上新增了isFinite(), isNaN()方法,用來取代傳統的全局isFinite(), isNaN()方法檢測數值是否有限、是不是NaN。ES5的isFinite(), isNaN()方法都會先將非數值類型的參數轉化爲Number類型再作判斷,這實際上是不合理的,最形成isNaN('NaN') === true
的奇怪行爲--'NaN'是一個字符串,可是isNaN卻說這就是NaN。而Number.isFinite()和Number.isNaN()則不會有此類問題(Number.isNaN('NaN') === false
)。(isFinite()同上)數據結構
ES6在Math對象上新增了Math.cbrt(),trunc(),hypot()等等較多的科學計數法運算方法,能夠更加全面的進行立方根、求和立方根等等科學計算。
a. 對象屬性變量式聲明。ES6能夠直接以變量形式聲明對象屬性或者方法,。比傳統的鍵值對形式聲明更加簡潔,更加方便,語義更加清晰。
let [apple, orange] = ['red appe', 'yellow orange']; let myFruits = {apple, orange}; // let myFruits = {apple: 'red appe', orange: 'yellow orange'};
尤爲在對象解構賦值(見優化部分b.)或者模塊輸出變量時,這種寫法的好處體現的最爲明顯:
let {keys, values, entries} = Object; let MyOwnMethods = {keys, values, entries}; // let MyOwnMethods = {keys: keys, values: values, entries: entries}
能夠看到屬性變量式聲明屬性看起來更加簡潔明瞭。方法也能夠採用簡潔寫法:
let es5Fun = { method: function(){} }; let es6Fun = { method(){} }
b. 對象的解構賦值。 ES6對象也能夠像數組解構賦值那樣,進行變量的解構賦值:
let {apple, orange} = {apple: 'red appe', orange: 'yellow orange'};
c. 對象的擴展運算符(...)。 ES6對象的擴展運算符和數組擴展運算符用法本質上差異不大,畢竟數組也就是特殊的對象。對象的擴展運算符一個最經常使用也最好用的用處就在於能夠輕鬆的取出一個目標對象內部所有或者部分的可遍歷屬性,從而進行對象的合併和分解。
let {apple, orange, ...otherFruits} = {apple: 'red apple', orange: 'yellow orange', grape: 'purple grape', peach: 'sweet peach'}; // otherFruits {grape: 'purple grape', peach: 'sweet peach'} // 注意: 對象的擴展運算符用在解構賦值時,擴展運算符只能用在最有一個參數(otherFruits後面不能再跟其餘參數) let moreFruits = {watermelon: 'nice watermelon'}; let allFruits = {apple, orange, ...otherFruits, ...moreFruits};
d. super 關鍵字。ES6在Class類裏新增了相似this的關鍵字super。同this老是指向當前函數所在的對象不一樣,super關鍵字老是指向當前函數所在對象的原型對象。
a. ES6在Object原型上新增了is()方法,作兩個目標對象的相等比較,用來完善'==='方法。'==='方法中NaN === NaN //false
實際上是不合理的,Object.is修復了這個小bug。(Object.is(NaN, NaN) // true
)
b. ES6在Object原型上新增了assign()方法,用於對象新增屬性或者多個對象合併。
const target = { a: 1 }; const source1 = { b: 2 }; const source2 = { c: 3 }; Object.assign(target, source1, source2); target // {a:1, b:2, c:3}
c. ES6在Object原型上新增了getOwnPropertyDescriptors()方法,此方法加強了ES5中getOwnPropertyDescriptor()方法,能夠獲取指定對象全部自身屬性的描述對象。結合defineProperties()方法,能夠完美複製對象,包括複製get和set屬性。
d. ES6在Object原型上新增了getPrototypeOf()和setPrototypeOf()方法,用來獲取或設置當前對象的prototype對象。這個方法存在的意義在於,ES5中獲取設置prototype對像是經過__proto__屬性來實現的,然而__proto__屬性並非ES規範中的明文規定的屬性,只是瀏覽器各大產商「私自」加上去的屬性,只不過由於適用範圍廣而被默認使用了,再非瀏覽器環境中並不必定就可使用,因此爲了穩妥起見,獲取或設置當前對象的prototype對象時,都應該採用ES6新增的標準用法。
d. ES6在Object原型上還新增了Object.keys(),Object.values(),Object.entries()方法,用來獲取對象的全部鍵、全部值和全部鍵值對數組。
a. 箭頭函數(核心)。箭頭函數是ES6核心的升級項之一,箭頭函數裏沒有本身的this,這改變了以往JS函數中最讓人難以理解的this運行機制。主要優化點:
Ⅰ. 箭頭函數內的this指向的是函數定義時所在的對象,而不是函數執行時所在的對象。ES5函數裏的this老是指向函數執行時所在的對象,這使得在不少狀況下this的指向變得很難理解,尤爲是非嚴格模式狀況下,this有時候會指向全局對象,這甚至也能夠歸結爲語言層面的bug之一。ES6的箭頭函數優化了這一點,它的內部沒有本身的this,這也就致使了this老是指向上一層的this,若是上一層仍是箭頭函數,則繼續向上指,直到指向到有本身this的函數爲止,並做爲本身的this。
Ⅱ. 箭頭函數不能用做構造函數,由於它沒有本身的this,沒法實例化。
Ⅲ. 也是由於箭頭函數沒有本身的this,因此箭頭函數 內也不存在arguments對象。(能夠用擴展運算符代替)
b. 函數默認賦值。ES6以前,函數的形參是沒法給默認值得,只能在函數內部經過變通方法實現。ES6以更簡潔更明確的方式進行函數默認賦值
function es6Fuc (x, y = 'default') { console.log(x, y); } es6Fuc(4) // 4, default
ES6新增了雙冒號運算符,用來取代以往的bind,call,和apply。(瀏覽器暫不支持,Babel已經支持轉碼)
foo::bar; // 等同於 bar.bind(foo); foo::bar(...arguments); // 等同於 bar.apply(foo, arguments);
答: Set是ES6引入的一種相似Array的新的數據結構,Set實例的成員相似於數組item成員,區別是Set實例的成員都是惟一,不重複的。這個特性能夠輕鬆地實現數組去重。
答: Map是ES6引入的一種相似Object的新的數據結構,Map能夠理解爲是Object的超集,打破了以傳統鍵值對形式定義對象,對象的key再也不侷限於字符串,也能夠是Object。能夠更加全面的描述對象的屬性。
答: Proxy是ES6新增的一個構造函數,能夠理解爲JS語言的一個代理,用來改變JS默認的一些語言行爲,包括攔截默認的get/set等底層方法,使得JS的使用自由度更高,能夠最大限度的知足開發者的需求。好比經過攔截對象的get/set方法,能夠輕鬆地定製本身想要的key或者value。下面的例子能夠看到,隨便定義一個myOwnObj的key,均可以變成本身想要的函數。
function createMyOwnObj() { //想把全部的key都變成函數,或者Promise,或者anything return new Proxy({}, { get(target, propKey, receiver) { return new Promise((resolve, reject) => { setTimeout(() => { let randomBoolean = Math.random() > 0.5; let Message; if (randomBoolean) { Message = `你的${propKey}運氣不錯,成功了`; resolve(Message); } else { Message = `你的${propKey}運氣不行,失敗了`; reject(Message); } }, 1000); }); } }); } let myOwnObj = createMyOwnObj(); myOwnObj.hahaha.then(result => { console.log(result) //你的hahaha運氣不錯,成功了 }).catch(error => { console.log(error) //你的hahaha運氣不行,失敗了 }) myOwnObj.wuwuwu.then(result => { console.log(result) //你的wuwuwu運氣不錯,成功了 }).catch(error => { console.log(error) //你的wuwuwu運氣不行,失敗了 })
答: Promise是ES6引入的一個新的對象,他的主要做用是用來解決JS異步機制裏,回調機制產生的「回調地獄」。它並非什麼突破性的API,只是封裝了異步回調形式,使得異步回調能夠寫的更加優雅,可讀性更高,並且能夠鏈式調用。
答: 若是看到問題十六,那麼就很好回答。問題十六提到了ES6統一了遍歷標準,制定了可遍歷對象,那麼用什麼方法去遍歷呢?答案就是用for...of。ES6規定,有所部署了載了Iterator接口的對象(可遍歷對象)均可以經過for...of去遍歷,而for..in僅僅能夠遍歷對象。
這也就意味着,數組也能夠用for...of遍歷,這極大地方便了數組的取值,且避免了不少程序用for..in去遍歷數組的惡習。
上面提到的擴展運算符本質上也就是for..of循環的一種實現。
答: async函數能夠理解爲內置自動執行器的Generator函數語法糖,它配合ES6的Promise近乎完美的實現了異步編程解決方案。
答: module、export、import是ES6用來統一前端模塊化方案的設計思路和實現方案。export、import的出現統一了前端模塊化的實現方案,整合規範了瀏覽器/服務端的模塊化方法,用來取代傳統的AMD/CMD、requireJS、seaJS、commondJS等等一系列前端模塊不一樣的實現方案,使前端模塊化更加統一規範,JS也能更加能實現大型的應用程序開發。
import引入的模塊是靜態加載(編譯階段加載)而不是動態加載(運行時加載)。
import引入export導出的接口值是動態綁定關係,即經過該接口,能夠取到模塊內部實時的值。
答:
一、經常使用箭頭函數來取代var self = this;
的作法。
二、經常使用let取代var命令。
三、經常使用數組/對象的結構賦值來命名變量,結構更清晰,語義更明確,可讀性更好。
四、在長字符串多變量組合場合,用模板字符串來取代字符串累加,能取得更好地效果和閱讀體驗。
五、用Class類取代傳統的構造函數,來生成實例化對象。
六、在大型應用開發中,要保持module模塊化開發思惟,分清模塊之間的關係,經常使用import、export方法。