想寫出優雅的代碼?試試這些ES6小tips

最近又重溫了ES6的文檔,發現除了箭頭函數,解構賦值,擴展運算符這樣經常使用的語法外,還有不少很給力的方法,不只使代碼更簡潔,還能夠提升代碼的健壯性,更令我意外的是,瀏覽器兼容大部分的方法,無需babel也可完美運行。因此以爲頗有必要整理一下,在項目中,拋棄陳舊的老古董寫法,升級爲ES6規範代碼。javascript

一.數組升級

1.擴展運算符之複製數組

//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

2.數組實例的find()和findIndex()

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
複製代碼

3.數組實例的includes()

該方法返回一個布爾值,表示某個數組是否包含給定的值。沒有該方法以前,咱們一般使用數組的indexOf方法,檢查是否包含某個值。babel

indexOf方法有兩個缺點,一是不夠語義化,它的含義是找到參數值的第一個出現位置,因此要去比較是否不等於-1,表達起來不夠直觀。二是,它內部使用嚴格相等運算符(===)進行判斷,這會致使對NaN的誤判。數據結構

[NaN].indexOf[NaN] //-1

[NaN].includes(NaN) //0
複製代碼

注:Map和Set數據結構有一個has方法,注意與includes區分。Map結構的has方法,是來查找鍵名的 Set結構的has方法,是用來查找鍵值的。ide

二.對象升級

1.Object.assign()

用於對象的合併,將原對象的全部可枚舉屬性,複製到目標對象上。函數

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能夠用來處理數組,可是會把數組視爲對象。

2.屬性的遍歷

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 或字符串,也不論是否可枚舉。

三. 函數升級

1.rest參數

用於獲取函數的多餘參數,這樣就不須要使用arguments對象了。

// arguments變量的寫法
function sortNumbers() {
  return Array.prototype.slice.call(arguments).sort();
}

// rest參數的寫法
const sortNumbers = (...numbers) => numbers.sort();
複製代碼

2.箭頭函數

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循環

for...of循環可使用的範圍包括數組、Set 和 Map 結構、某些相似數組的對象(好比arguments對象、DOM NodeList 對象)、後文的 Generator 對象,以及字符串。

1.用法

數組:

//爲對象添加屬性和方法
//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'
複製代碼

2.與其餘遍歷語法的比較

for...in循環有幾個缺點。

  • 數組的鍵名是數字,可是for...in循環是以字符串做爲鍵名「0」、「1」、「2」等等。
  • for...in循環不只遍歷數字鍵名,還會遍歷手動添加的其餘鍵,甚至包括原型鏈上的鍵
  • 某些狀況下,for...in循環會以任意順序遍歷鍵名。 總之,for...in循環主要是爲遍歷對象而設計的,不適用於遍歷數組。

forEach循環的缺點是沒法中途跳出forEach循環,break命令或return命令都不能奏效。

與之相對的,for...of有以下優勢:

  • 有着同for...in同樣的簡潔語法,可是沒有for...in那些缺點。
  • 不一樣於forEach方法,它能夠與break、continue和return配合使用。
  • 提供了遍歷全部數據結構的統一操做接口。

五.參考網址

http://es6.ruanyifeng.com/#docs/iterator#for---of-%E5%BE%AA%E7%8E%AF

相關文章
相關標籤/搜索