【前言】本文“嚴重參考” 自阮一峰老師寫的ES6文檔,在此我鄭重感謝他沉默無聲的幫助
總結一下ES6為 javascript中的 對象/數組/函數 這JS三巨頭所提供的更簡潔優雅的書寫方式,以及擴展的API。
對象篇
- 屬性名簡潔表示法, 當對象的屬性名和作為屬性值的變量名名稱相同時,可只寫屬性名
var name = "彭湖灣" var obj = { name: name }
可簡寫為
var name = "彭湖灣" var obj = { name }
- 如果對象的屬性是函數,可簡寫為類似於“函數聲明”的形式:
var obj = { methods: function () {} }
可簡寫為
var obj = { methods () {
// ... } }
- 對象字面量的屬性名表達式
以前你只能對單一的對象屬性使用表達式:obj['a' + 'b'] = value
現在你可以在一個對象字面量里對屬性名使用表達式:
var obj = { ['a' + 'b']: value }
- Object.assign(target, source1, source2 ....) 可把source1,source2等第二個參數以后的對象合並到target
1.規則是對於同名屬性, 后面的對象會覆蓋前面的,如source1覆蓋target, source2會覆蓋source1
var target = { a: 1, b: 1 }; var source1 = { b: 2, c: 2 }; var source2 = { c: 3 }; Object.assign(target, source1, source2); target // {a:1, b:2, c:3}
2. Object.assign的合並功能僅止於第一層屬性,也就是說, 如果兩個合並對象(如source1和source2)有一個第一層的同名屬性,並且這個屬性也是個有屬性的對象,那么Object.assign不會“進入”位於第二層的屬性對象,對其屬性進行合並,而是簡單地用后面對象的第一層屬性替代前面對象的第一層屬性
var target = { a: { b: 'c', d: 'e' } } var source = { a: { b: 'hello' } } Object.assign(target, source)
結果是
{ a: { b: 'hello' } }
不是
{ a: { b: 'hello', d: 'e' } }
- 遍歷屬性對象的幾個API對比:
1.for...in 遍歷對象自身屬性和原型中的屬性, 且要求是可枚舉屬性
2. Object.keys(obj),返回一個數組, 遍歷自身屬性, 不包括原型屬性, 且要求是可枚舉的
3. Object.getOwnPropertyNames(obj) 返回一個數組,遍歷自身屬性, 不包括原型屬性, 且不要求是可枚舉的
4.Object.values(): 和Object.keys(obj)類似,不過遍歷的是屬性值
5.Object.entries() 和Object.keys(obj)類似,不過遍歷的是屬性名/值對,返回一個二維數組:
[ ["key1", "value1"], ["key2", "value2"] ]
關鍵對比
1.for...in 和Object.keys(obj)/Object.getOwnPropertyNames(obj), 前者取得原型中的屬性,后兩者不取
2.Object.getOwnPropertyNames(obj) 和Object.keys(obj), 都是只返回遍歷自身屬性組成的數組,前者無論是否可枚舉都返回, Object.keys(obj)只返回可枚舉屬性
3.Object.keys(obj) , Object.values(), Object.entries() 分別遍歷對象的鍵, 值,鍵值對
數組篇
- Array.of 將一組參數作為數組元素組成數組, 如
Array.of(1, 2, 3) // [1,2,3]
出現原因: 彌補Array構造函數的不足:
Array構造函數因為接收參數的不同行為表現差異非常巨大
1. 當接收一個參數的時候,它會以為你傳的是數組的長度,從而創建一個對應長度的“空”數組
Array(3) // [, , ,]
2. 當接收多個參數的時候,它會以為你傳的是數組元素, 從而創建一個指定數組元素的數組
Array(1, 2, 3) // [1, 2, 3]
- Array.from將兩類對象都轉為數組
1類數組對象(如函數內部的arguments,DOM操作產生的NodeList集合)
2 ES6新增加的Set對象, Map對象
都轉為真正的數組
轉化類數組對象
function foo() { var args = Array.from(arguments); // arguments從對象變成了數組 }
轉化ES6新增加的Set對象, Map對象
let namesSet = new Set(['a', 'b']) Array.from(namesSet) // ['a', 'b']
- find方法,用於在一個數組中找到第一個符合條件的數組元素
[1, 2, 3, -1].find((n) => n < 0) // -1
ES5中我們可能會使用IndexOf方法來尋找一個特定的元素,但它的局限性在於indexof只能以數組元素的值作為查找條件,而find方法則更加靈活, 它提供了一個以數組元素為參數的函數供你做更加靈活的操作,並取得第一個返回true的數組元素
- fill方法, 通過array.fill(value), 可以將array數組的所有值都寫為value
一般可以用於初始化空數組:
new Array(4).fill(1) // [1, 1, 1,1]
- includes方法 檢測數組中是否含有某個元素, 返回true或者false
【注意】array.indexOf(數組元素) === -1 這個常用於判斷條件的表達式可以用 includes方法去替代
[1, 2, 3].includes(2) // true [1, 2, 3].includes(4) // false
函數篇
- 函數參數在ES6下可以設置默認值
function log(x, y = 'World') { console.log(x, y); } log('Hello') // Hello World
- rest 參數
可以通過“...”的運算符把接收到的函數參數合為數組放入緊跟“...”的變量中
function fn(...args) { } fn(1, 2, 3) // 此時 args = [1,2,3]
【注意】 函數的reset參數可以看做是擴展運算符的“逆運算”
- name屬性
函數可取name屬性
function fn() {} fn.name // "fn"
- 箭頭函數
ES6引入了箭頭函數,它有幾大作用:
1. 使我們能通過一種更為簡潔的方式書寫函數
2. 箭頭函數綁定了this對象, 減少了this綁定丟失所造成的麻煩
- 在javascript中, 大多數變量的查找的都是靜態的,而不是動態的, 或者說是變量所在的作用域是定義時候決定的,而不是運行時決定
- 但this卻恰好相反, this的綁定是動態的, 是運行時決定的, 這有時候就導致了讓人苦惱的this綁定丟失問題
用一段代碼展示一下普通函數(相比於箭頭函數)所存在this綁定丟失的問題
function foo() { setTimeout( function () { console.log('id:', this.id); }, 100); } var id = 21; foo.call({ id: 42 }); // id: 21
為什么輸出的是21不是42呢? 因為setTimeout里的函數是異步執行的,當調用foo.call({ id: 42 })的時候setTimeout里的函數並沒有立即得到執行,
所以setTimeout()調用的時候,它運行在與所在函數完全分離的執行環境上。這時候this指向的是window,而不是{ id: 42 } (在 ES6嚴格模式下是undefined)
但箭頭函數的this是靜態綁定的, 所以能很好地解決這個問題:
function foo() { setTimeout(() => { console.log('id:', this.id); }, 100); } var id = 21; foo.call({ id: 42 }); // id: 42
如果園友看到這里了, 那么請容我道個歉, 在這篇文章里, 其實多處“參考”了《ES6入門》中的例子, 比起自己親手寫的代碼,多少可能會讓讀者們感到有些難理解,因為這幾天實在挺累的,所以寫這篇文章的時候有些心力不足,見諒。
資料來源:
1. MDN https://developer.mozilla.org/zh-CN/
2. ECMAScript 6入門 http://es6.ruanyifeng.com/