最近又重溫了ES6的文檔,發現除了箭頭函數,解構賦值,擴展運算符這樣經常使用的語法外,還有不少很給力的方法,不只使代碼更簡潔,還能夠提升代碼的健壯性,更令我意外的是,瀏覽器兼容大部分的方法,無需babel也可完美運行。因此以爲頗有必要整理一下,在項目中,拋棄陳舊的老古董寫法,升級爲ES6規範代碼。javascript
//es5作法
const a1 = [1, 2]
const a2 = a1.concat()
a2[0] = 2
a1 //[1,2] 修改a2不會對a1有影響
複製代碼
擴展運算符提供了複製數組的簡便寫法:java
//es6作法
const a1 = [1, 2]
const a2 = [...a1]
//or
const [...a2] = a1
a2[0] = 2
a1 //[1,2] 修改a2不會對a1有影響
複製代碼
注:上述複製的過程是深拷貝,可是要注意的一點是,concat和擴展運算符用作合併數組時,都是淺拷貝。es6
find方法,用於找出第一個符合條件的數組成員,它的參數是一個回調函數,全部數組成員依次執行該回調函數,直到找出第一個返回值爲true的成員,而後返回該成員。若是沒有符合條件的成員,則返回undefined。數組
//es5作法
const arr = [1,5,10,15]
for(var i=0;i<arr.length;i++) {
if(arr[i]>5) {
return arr[i]
}
} //10
//es6作法
[1,5,10,15].find(function(value,index,arr) {
return value > 5
}) //10
複製代碼
另外,這兩個方法均可以發現NaN,彌補了indexOf方法的不足。瀏覽器
[NaN].indexOf[NaN] //-1
[NaN].findIndex(y => Object.is(NaN,y)) //0
複製代碼
該方法返回一個布爾值,表示某個數組是否包含給定的值。沒有該方法以前,咱們一般使用數組的indexOf方法,檢查是否包含某個值。babel
indexOf方法有兩個缺點,一是不夠語義化,它的含義是找到參數值的第一個出現位置,因此要去比較是否不等於-1,表達起來不夠直觀。二是,它內部使用嚴格相等運算符(===)進行判斷,這會致使對NaN的誤判。數據結構
[NaN].indexOf[NaN] //-1
[NaN].includes(NaN) //0
複製代碼
注:Map和Set數據結構有一個has方法,注意與includes區分。Map結構的has方法,是來查找鍵名的 Set結構的has方法,是用來查找鍵值的。ide
用於對象的合併,將原對象的全部可枚舉屬性,複製到目標對象上。函數
object.assign拷貝的屬性是有限制的,只拷貝源對象自身的屬性(不拷貝繼承屬性,也不拷貝不可枚舉的屬性)ui
//爲對象添加屬性和方法
//es6
class Point {
constructor(x, y) {
Object.assign(this, {x, y});
}
}
Object.assign(Point.prototype, {
addPoint(arg1, arg2) {
···
}
});
複製代碼
這個方法很經常使用,但一些細節問題仍是要拎出來提醒本身注意一下。
(1)淺拷貝
Object.assign方法實行的是淺拷貝,而不是深拷貝。也就是說,若是源對象某個屬性的值是對象,那麼目標對象拷貝獲得的是這個對象的引用。
(2)同名屬性的替換
對於這種嵌套的對象,一旦遇到同名的屬性,Object.assign的處理方法是替換,而不是添加。要特別注意!!
(3)數組的處理
Object.assign能夠用來處理數組,可是會把數組視爲對象。
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 或字符串,也不論是否可枚舉。
用於獲取函數的多餘參數,這樣就不須要使用arguments對象了。
// arguments變量的寫法
function sortNumbers() {
return Array.prototype.slice.call(arguments).sort();
}
// rest參數的寫法
const sortNumbers = (...numbers) => numbers.sort();
複製代碼
ES6 容許使用「箭頭」(=>)定義函數。
// arguments變量的寫法
function sortNumbers() {
return Array.prototype.slice.call(arguments).sort();
}
// rest參數的寫法
const sortNumbers = (...numbers) => numbers.sort();
複製代碼
注意點:
(1)函數體內的this對象,就是定義時所在的對象,而不是使用時所在的對象。
(2)不能夠看成構造函數,也就是說,不可使用new命令,不然會拋出一個錯誤。
(3)不可使用arguments對象,該對象在函數體內不存在。若是要用,能夠用 rest 參數代替。
for...of循環可使用的範圍包括數組、Set 和 Map 結構、某些相似數組的對象(好比arguments對象、DOM NodeList 對象)、後文的 Generator 對象,以及字符串。
數組:
//爲對象添加屬性和方法
//es6
const arr = ['red', 'green', 'blue'];
for(let v of arr) {
console.log(v); // red green blue
}
複製代碼
Set 和 Map 結構
var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]);
for (var e of engines) {
console.log(e);
}
// Gecko
// Trident
// Webkit
var es6 = new Map();
es6.set("edition", 6);
es6.set("committee", "TC39");
es6.set("standard", "ECMA-262");
for (var [name, value] of es6) {
console.log(name + ": " + value);
}
// edition: 6
// committee: TC39
// standard: ECMA-262
複製代碼
類數組的對象
// 字符串
let str = "hello";
for (let s of str) {
console.log(s); // h e l l o
}
// DOM NodeList對象
let paras = document.querySelectorAll("p");
for (let p of paras) {
p.classList.add("test");
}
// arguments對象
function printArgs() {
for (let x of arguments) {
console.log(x);
}
}
printArgs('a', 'b');
// 'a'
// 'b'
複製代碼
for...in循環有幾個缺點。
forEach循環的缺點是沒法中途跳出forEach循環,break命令或return命令都不能奏效。
與之相對的,for...of有以下優勢:
http://es6.ruanyifeng.com/#docs/iterator#for---of-%E5%BE%AA%E7%8E%AF