數組實例的遍歷方法es6
const arr=['red', 'green', 'blue']; arr.forEach(function(element, index) { console.log(element);// red green blue console.log(index);// 0 1 2 });
forEach這種寫法的問題是,沒法中途跳出forEach循環,break命令或return命令都不能奏效。數組
JavaScript原有的循環,只能得到對象的鍵名,不能直接獲取鍵值。數據結構
var arr = ['a', 'b', 'c', 'd', 'e']; for(let i in arr) { console.log(i);//0 1 2 3 4 }
for(let index in arr) {
console.log(arr[index]);// a b c d e
}
let es6 = { edition: 6, committee: "TC-39", standard: "ECMA-262" }; for(let e in es6) { console.log(e); } //edition //committee //standard
for...in循環有幾個缺點:ide
數組鍵名是數字,可是for...in循環是以字符串做爲鍵名"0","1","2"等函數
for...in循環不只遍歷數字鍵名,還會遍歷手動添加的其它鍵,甚至包括原型鏈上的鍵。spa
某些狀況下,for...in循環會以任意順序遍歷鍵名。設計
總之,for...in循環主要是爲遍歷對象爲設計的,不適用於遍歷數組。code
ES6借鑑C++、Java、C#和Python語言,引入了for...of循環,做爲遍歷全部數據結構的統一的方法。一個數據結構只要部署了Symbol.iterator屬性,就被視爲具備iterator接口,就能夠用for...of循環遍歷它的成員。也就是說,for...of循環內部調用的是數據結構的Symbol.iterator方法。for...of循環可使用的範圍包括數組、Set和Map結構、某些相似數組的對象(好比arguments對象、DOM NodeList對象)、Generator對象以及字符串。對象
數組原生具備iterator接口(即默認部署了Symbol.iterator屬性),for...of循環本質上就是調用這個接口產生的遍歷器,容許遍歷得到鍵值;blog
var arr = ['a', 'b', 'c', 'd', 'e']; for(let i of arr) { console.log(i);//a b c d e }
for...of循環能夠代替數組實例的forEach方法
for...of循環調用遍歷器接口,數組的遍歷器接口只返回具備數字索引的屬性;這一點與for...in也不同。
let arr = [1,3,5]; arr.foo = 'hello'; for(let i in arr) { console.log(i);//'1', '3', '5', 'foo' } for(let i of arr) { console.log(i);//'1', '3', '5' }
Set和Map結構也原生具備Iterator接口,能夠直接使用for...of循環
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
Set和Map遍歷的順序是按照各個成員被添加進數據結構的前後順序。其次,Set結構遍歷,返回的是一個值。Map結構遍歷返回的是一個數組,該數組的兩個成員分別爲當前Map成員的鍵名和鍵值。
for...of循環,得到數組的索引,能夠藉助數組實例的entries方法和keys方法。
let arr = ["a", "b", "c"]; for(let pair of arr.entries()) { console.log(pair); } //[0, 'a'] //[1, 'b'] //[2, 'c']
for...of遍歷相似數組的對象(String、DOM NodeList、arguments)
//字符串 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...of循環還可以正確識別32位UTF-16字符
for (let x of 'a\uD83D\uDC0A) { console.log(x); } //'a' //'\uD83D\uDC0A'
並非全部相似數組的對象都具備Iterator接口,一個方法是用Array.from方法將其轉換爲數組
let arrayLike = [length: 2, 0: 'a', 1: 'b']; for(let x of array.from(arrayLike)) { console.log(x); }
對於普通的對象,for...of結構不能直接使用,必須部署Iterator接口後才能使用。一種解決方法是將對象的鍵名生成一個數組,而後遍歷這個數組:
for(let key of Object.keys(someObject)) { console.log(key + ":" + someObject[key]); }
另外一個方法是使用Generator函數
function* entries(obj) { for(let key of Object.keys(obj)) { yield [key, obj[key]]; } } for(let [key, value] of entries(obj)) { console.log(key, '->', value); } //a -> 1 //b -> 2 //c -> 3
for...of相對其它遍歷方法,有如下優勢:
有着同for...in同樣簡潔的語法,可是沒有for...in那些缺點;
不一樣於forEach方法,它能夠與break、continue和return配合使用
提供了遍歷全部數據結構的統一操做接口
for(var n of fibonacci) { if(n>1000) break; console.log(n); }
參考: