本文大量參考了阮一峯老師的開源教程ECMAScript6入門和MDN,適合新手入門或者對ES6經常使用知識點進行全面回顧,目標是以較少的篇幅涵蓋ES6及部分ES7在實踐中的絕大多數使用場景。更全面、更深刻的請進入上面的教程。若是您以爲有遺漏的常見知識點或者錯誤的地方,請評論指出!javascript
新的變量聲明方式,提供變量的塊級做用域,同時經過一些限制來更防止咱們犯錯誤。也就是說是更好的聲明變量的方式vue
1)let/const與var的區別是提供了塊級做用域以及變量建立時不會當即初始化java
2)在同一個做用域內let/const禁止重複聲明相同的變量es6
var a = 1 let a = 2 // SyntaxError
3)let聲明的變量可從新賦值,const聲明的變量不能從新賦值,即常量。ajax
4)暫時性死區:在當前做用域,使用的變量已經存在,可是在代碼執行到變量聲明前禁止訪問。vuex
var tmp = 123 if (true) { tmp = 'abc' // ReferenceError let tmp }
1)由於能建立塊級做用域,因此常見於if和for中json
for (let i = 0; i < arr.length; i++) { console.log(arr[i]) }
2)const在實踐中經常使用來聲明一個對象,以後能夠再對這個對象的屬性進行修改數組
const foo = { name: 'bar' } foo.name = 'baz' console.log(foo)
按照阮一峯大神的說法:ES6容許按照必定模式,從數組和對象中提取值,對變量進行賦值,這被稱爲解構(Destructuring)。也就是說經過模式匹配來進行變量賦值。數據結構
1)數組基本用法app
let [a, b, c] = [1, 2, 3] a //1 b //2 c //3
2)對象基本用法
let { foo, bar } = { foo: "aaa", bar: "bbb" } foo // "aaa" bar // "bbb"
3)函數參數的解構賦值
如在vuex中action不使用解構以下:
actions: { increment (context) { context.commit('increment') } }
使用解構
actions: { increment ({ commit }) { commit('increment') } }
4)支持不徹底解構
let [foo, bar] = [1, 2, 3]
5)若是解構不成功,變量的值就等於undefined,同時解構賦值容許指定默認值,默認值生效的條件是對象的屬性值嚴格等於undefined。
1)交換變量的值
[x, y] = [y, x]
2)提取JSON數據
let jsonData = { id: 42, status: "OK", data: [867, 5309] } let { id, status, data: number } = jsonData console.log(id, status, number) // 42, "OK", [867, 5309]
3)函數參數的默認值
jQuery.ajax = function (url, { async = true, beforeSend = function () {}, cache = true, complete = function () {}, crossDomain = false, global = true, // ... more config }) { // ... do stuff }
4)指定加載模塊的什麼功能
import { mapActions } from 'vuex'
箭頭函數能夠用來替換函數表達式,不用寫function,更加簡化。也就是說是函數表達式的簡化方式
1)注意箭頭函數中的this指向外層的this
2)沒法用call/apply/bind來改變this指向。
3)在ES6中,會默認採用嚴格模式,所以默認狀況下this不是指向window對象,而是undefined。
<script type="text/javascript"> setTimeout(() => console.log(this), 1000) // undefined,不是window </script>
4)不可使用arguments對象,該對象在函數體內不存在。若是要用,能夠用rest參數代替。
關鍵是你須要this指向什麼
默認參數就是設置參數默認值,rest參數(翻譯爲不具名參數,也叫作剩餘參數)是將傳入的未具名的參數做爲一個數組集合
以下,默認參數給參數賦一個默認值,rest參數使用三個點(...)加數組集合名
function foo(arg1 = 1, ...restArg){ console.log(arg1, restArg) } foo(undefined, 2, 3, 4) // 1, [2, 3, 4] foo(2, 3, 4) // 2, [3, 4]
同rest參數同樣,也是三個點。它比如rest參數的逆運算,將一個數組轉爲用逗號分隔的參數序列。所以經常使用於函數調用。
1)合併數組
let newArr = [...arr1, ...arr2, ...arr3]
2)與解構賦值結合
// ES5 a = list[0], rest = list.slice(1) // ES6 [a, ...rest] = list
3)將字符串轉爲數組
[...'test'] // [ "t", "e", "s", "t"]
1)屬性簡寫,當對象的一個屬性名稱與本地變量名相同的時候,能夠省略冒號和值
var foo = 'bar' var baz = {foo} baz // {foo: "bar"}
2)屬性名錶達式,能夠在以對象字面量方式定義對象是使用表達式做爲屬性名
// ES5只能這樣 obj['a' + 'bc'] = 123 // ES6還能這樣 let obj = { ['a' + 'bc']: 123 }
3)方法簡寫,省去:和function
const foo = { bar () { console.log('1') } }
更好的判斷方法,與===的不一樣有兩點:一是+0不等於-0,二是NaN等於自身。
NaN === NaN // false Object.is(NaN, NaN) // true
1)Object.assign方法用於對象的合併,用法與jQuery和underscore的extend方法相似,並且一樣會改變target。
Object.assign(target, source1, source2)
2)只拷貝源對象的自身屬性(不拷貝繼承屬性),也不拷貝不可枚舉的屬性(enumerable: false)。
3)Object.assign方法實行的是淺拷貝,而不是深拷貝。
用來設置一個對象的prototype對象,返回參數對象自己
Object.setPrototypeOf(object, prototype)
Object.getPrototypeOf方法能夠用來從子類上獲取父類。所以,可使用這個方法判斷,一個類是否繼承了另外一個類。參見下面類與繼承章節
對象的每一個屬性都有一個描述對象(Descriptor),Object.getOwnPropertyDescriptor方法能夠獲取該屬性的描述對象。這個描述對象有value、writable、enumerable、configurable四大屬性。
ES5下面三個操做會忽略enumerable爲false的屬性。
ES6新增的操做Object.assign(),也會忽略enumerable爲false的屬性,只拷貝對象自身的可枚舉的屬性。
ES6一共有5種方法能夠遍歷對象的屬性。
(1)for...in
for...in循環遍歷對象自身的和繼承的可枚舉屬性(不含Symbol屬性)。
(2)Object.keys(obj)
Object.keys返回一個數組,包括對象自身的(不含繼承的)全部可枚舉屬性(不含Symbol屬性)。
(3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一個數組,包含對象自身的全部屬性(不含Symbol屬性,可是包括不可枚舉屬性)。
(4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一個數組,包含對象自身的全部Symbol屬性。
(5)Reflect.ownKeys(obj)
Reflect.ownKeys返回一個數組,包含對象自身的全部屬性,無論屬性名是Symbol或字符串,也不論是否可枚舉。
以上的5種方法遍歷對象的屬性,都遵照一樣的屬性遍歷的次序規則。
大多數時候,咱們只關心對象自身的可枚舉屬性。因此,儘可能不要用for...in循環,而用Object.keys()代替。
之前判斷一個字符串是否包含某個字符串只能經過indexOf的值是否大於-1來判斷,如今新增了三種方法:
includes():表示是否包含該字符串。
startsWith():表示該字符串是否在頭部。
endsWith():表示該字符串是否在尾部。
'hello world'.includes('hello') // true
和handlebars那些模板引擎功能相似,有模板字符串能夠不用拼接字符串了
用反引號``將整個字符串包裹起來,${}表示一個變量或者一個表達式,能夠嵌套
const tmpl = addrs => ` <table> ${addrs.map(addr => ` <tr><td>${addr.first}</td></tr> <tr><td>${addr.last}</td></tr> `).join('')} </table> ` const data = [ { first: 'Jane', last: 'Bond' }, { first: 'Lars', last: 'Croft' }, ] console.log(tmpl(data))
函數名後面緊接一個模板字符串。該函數將被調用來處理這個模板字符串。這被稱爲「標籤模板」功能(tagged template)。當字符串模板有變量時,函數的第一個參數爲被變量分開的字符串組成的數組,後面的參數依次爲變量,這些變量的參數序列可使用rest參數。
var a = 5 var b = 10 tag`Hello ${ a + b } world ${ a * b }` // 等同於 tag(['Hello ', ' world ', ''], 15, 50)
Array.of方法用於將一組值,轉換爲數組。能夠替代Array,且其行爲很是統一,不像Array只有一個正整數參數n時,會生成n個空位構成的數組
Array.of(1) // [1] Array.of(1, 2, 3) // [1, 2, 3] Array(1) // [undefined * 1],其實不是undefined,是空位,以下可證實二者並不同 0 in [undefined, undefined, undefined] // true 0 in [, , ,] // false Array(1, 2, 3) // [1, 2, 3]
Array.from方法用於將兩類對象轉爲真正的數組:類數組對象(array-like object)和可遍歷(iterable)對象(包括ES6新增的數據結構Set和Map)。Array.from還能夠接受第二個參數,做用相似於數組的map方法,用來對每一個元素進行處理,將處理後的值放入返回的數組。
Array.from({'0': 'a', length: 1}) // ['a'] Array.from('hello') // ['h', 'e', 'l', 'l', 'o'],由於字符串有Iterator接口,可遍歷 Array.from([1, 2, 3], (x) => x * x) // [1, 4, 9]
常見使用場景:
1)轉換NodeList集合。常見的相似數組的對象是DOM操做返回的NodeList集合,以及函數內部的arguments對象。可是後者使用rest參數更簡便
// NodeList對象 let elementDivList = document.querySelectorAll('div') Array.from(elementDivList).forEach(function (div) { console.log(div) })
2)數組去重。與下面要講到的Set配合便可很簡單地實現數值去重。
var arr = [1, 3, 5, 5, 8, 3, 2] var uniqueArr = Array.from(new Set(arr)) console.log(uniqueArr) // [1, 3, 5, 8, 2]
Array.prototype.copyWithin(target, start = 0, end = this.length)
它接受三個參數。
[1, 2, 3, 4, 5].copyWithin(0,2) // [3, 4, 5, 4, 5] /* 從索引2開始讀取數據,到數組尾部中止,即讀到(3, 4, 5),而後從索引0開始替換數據 */
找到第一個符合條件的item(項)或index(索引),前者至關於underscore中的first方法,後者則和underscore中的同名方法一致。另外,這兩個方法均可以藉助Object.is發現NaN,彌補了數組的IndexOf方法的不足。
[1, 2, 3, 4].find(x => x > 2) // 3 [1, 2, 3, 4].findIndex(x => x > 2) // 2 [NaN].findIndex(x => Object.is(NaN, x)) // 0
Array.prototype.fill(fillItem, start = 0, end = this.length) [1, 3, 6, 11, 4].fill(10,2) // [1, 3, 10, 10, 10]
與字符串的includes方法相似。該方法屬於ES7,但Babel轉碼器已經支持。
[1, 2, 3].includes(3, 3) // false [1, 2, 3].includes(3, -1) // true [NaN].includes(NaN) // true
ES6中增長了兩個新的數據結構:Set和Map。Set是不包含重複值的列表,而Map則是鍵與相對應的值的集合。
Set是不包含重複值的有序列表。
1)Set構造函數能夠接受一個數組(或相似數組的對象)做爲參數,用來初始化。
const set = new Set([1, 2, 3, 4, 4]) console.log(set)
2)四個操做方法(add()、delete()、has()、clear())和一個屬性(size),使用方法根據名字和下面例子就知道了
const s = new Set() s.add(1).add(2).add(2) // 注意2被add了兩次 s.size // 2 s.has(1) // true s.has(2) // true s.has(3) // false s.delete(2) s.has(2) // false s.add(3) s.size // 2 s.clear() s.size // 0
3)三個遍歷器生成函數(keys()、values()、entries())和一個遍歷方法(forEach())
keys方法、values方法、entries方法返回的都是遍歷器對象(詳見Iterator)。都這可使用遍歷器對象的方法for...of進行遍歷。因爲 Set 結構沒有鍵名,只有鍵值(或者說鍵名和鍵值是同一個值),因此keys方法和values方法的行爲徹底一致。forEach方法與ES5數組的forEach相似。
let set = new Set(['red', 'green', 'blue']) for (let item of set.keys()) { console.log(item) } // red // green // blue for (let item of set.values()) { console.log(item) } // red // green // blue for (let item of set.entries()) { console.log(item) } // ["red", "red"] // ["green", "green"] // ["blue", "blue"] set.forEach((value, key) => console.log(value, key))
4)Set轉化爲數組,有兩種方法:...擴展運算符和Array.from()
這二者可互換,所以前面提到的使用Array.from()來數組去重也能夠這樣作:[...new Set(arr)]
// 方法一 let set = new Set([1, 2, 3]) set = new Set([...set].map(val => val * 2)) // set的值是2, 4, 6 // 方法二 let set = new Set([1, 2, 3]) set = new Set(Array.from(set, val => val * 2)) // set的值是2, 4, 6
一種由鍵值對集合構成的數據結構,相似於對象,可是「鍵」的範圍不限於字符串,各類類型的值(包括對象)均可以看成鍵。
const m = new Map(); const o = {p: 'Hello World'}; m.set(o, 'content') m.get(o) // "content"
1)Set構造函數能夠接收任何一個具備Iterator接口的數據結構做爲參數
const set = new Set([ ['foo', 1], ['bar', 2] ]) const m1 = new Map(set) m1.get('foo') // 1
2)5個操做方法(set(key, value)、get(key)、has(key)、delete(key)、clear())和一個屬性(size)
3)遍歷生成函數和遍歷方法和Set相似,Map結構的默認遍歷器接口(Symbol.iterator屬性),就是entries方法。
map[Symbol.iterator] === map.entries // true
4)Map轉爲數組,使用...擴展運算符
WeakSet、WeakMap分別和Set、Map相似,不過存儲的是對象的弱引用方式,這樣在內存管理上更加容易優化。