在學習循環方法以前,先理解循環結構的執行步驟:javascript
一、聲明循環變量;java
二、判斷循環條件;數組
三、執行循環體操做;瀏覽器
四、更新循環變量;緩存
五、循環執行2-4,直到條件不成立,跳出循環。數據結構
var arr = [1, 2, 3, 4, 5];
for (let i = 0, len = arr.length; i < len; i++) {
console.log(`索引:${i},元素:${arr[i]}`);
}
// 這裏建議緩存數組長度,數組較大時對於性能有比較客觀的提高。
// 使用了v8引擎的瀏覽器(有Loop-invariant code motion特性)會自動將length屬性移到循環體外並緩存起來,
// 可是非v8瀏覽器(這裏特指IE)仍是要緩存的,並且緩存起來總沒壞處。
複製代碼
在for循環中定義的新變量至關於在循環體外定義的變量,因此能夠寫成以下格式。函數
var i = 0, len = arr.length;
for (; i < len; i++) {
console.log(`索引:${i},元素:${arr[i]}`);
}
複製代碼
每次循環執行結束都會對i進行增量操做(增量能夠爲負數),因此能夠將更新變量寫在代碼塊後面。而i++
只是其中經常使用寫法,也能夠是i = i + 2
等其餘方式。oop
var i = 0, len = arr.length;
for (; i < len;) {
console.log(`索引:${i},元素:${arr[i]}`);
i++;
}
複製代碼
當指定條件爲true
時循環一段代碼塊。注意:必定要對條件中使用的變量進行遞增,若是不進行遞增,循環就不會結束,這將會致使瀏覽器崩潰。性能
var i = 0;
while (i < 5) {
console.log(i);
i++;
}
複製代碼
do...while
循環和while
循環相似,區別在於do...while
會先執行一次循環體,而後再判斷循環條件,只要條件爲true
就會重複循環。學習
var i = 0;
do {
console.log(i);
i++;
}
while (i < 5);
複製代碼
在while
和do...while
中使用continue
要注意:continue
不能放在更新變量以前使用,不然循環不會結束形成瀏覽器崩潰。
for...in
可用於遍歷對象的可枚舉屬性,包括自有屬性、繼承自原型的屬性,不建議用來遍歷數組。
var obj = {a: 1, b: 2,};
for (let i in obj) { // i是對象的屬性名
console.log(`屬性:${i},值:${obj[i]}`);
}
Object.defineProperty(obj, "c", {value: 3,}); // 增長不可枚舉的屬性c
Object.prototype.d = 4;
for(var i in obj){
console.log(`屬性:${i},值:${obj[i]}`);
}
複製代碼
for...of
是ES6新增的方法,主要用來遍歷具備iterator
接口的數據集合,讀取數據集合的鍵值。一個數據結構只要部署了Symbol.iterator
屬性,就被視爲具備iterator
接口,就能夠用for...of
來遍歷它的成員。因此for...of
能夠用來遍歷數組、Set
和Map
結構、某些相似數組的對象(如arguments
對象)和字符串等,由於這些數據結構原生部署了iterator
接口。而普通對象不具有iterator
接口,不能直接用來遍歷普通對象。
var arr = [1, 2, 3];
for (let item of arr) { // item是數組每一項的值
console.log(`元素:${item}`);
}
for (let item of arr.values()) {
console.log(`元素:${item}`);
}
複製代碼
想要獲取數組的索引,能夠用數組實例的keys()
或者entries()
方法
for (let index of arr.keys()) {
console.log(`索引:${index}`);
}
for (let [index, item] of arr.entries()) {
console.log(`索引:${index},元素:${item}`);
}
複製代碼
遍歷字符串。
var str = "hello";
for (let item of str) {
console.log(item); // h e l l o
}
複製代碼
遍歷Map
對象
var myMap = new Map();
myMap.set('a', 1);
myMap.set('b', 2);
myMap.set('c', 3);
for (let [key, value] of myMap) {
console.log(`鍵名:${key},鍵值:${value}`); // Map返回一個數組,分別是當前Map成員的鍵名和鍵值
}
// 獲取鍵
for (let key of myMap.keys()) {
console.log(`鍵名:${key}`);
}
// 獲取值
for (let value of myMap.values()) {
console.log(`鍵值:${value}`);
}
複製代碼
遍歷Set
對象
var maSet = new Set(arr);
for (let value of maSet) {
console.log(value); // Set返回的是一個值
}
// 遍歷Map和Set對象的順序是按照各個成員被添加進數據結構的順序。
複製代碼
遍歷arguments
對象
function printArguments() {
for (let item of arguments) {
console.log(item);
}
}
printArguments('a', 'b'); // 'a' 'b'
複製代碼
map()
方法返回一個新的數組,它對原數組的每個值做必定的處理後放到新的數組裏面,而後返回新數組。
按照原始數組的元素順序依次處理元素,不會對空數組進行檢測,也不會改變原數組,不能使用break
和continue
語句。
var arr = [1, 2, 3];
var obj = {a: 2};
var newArr = arr.map(function(value, index, arr) {
// value爲當前元素
// index爲當前元素的索引值,可省略
// arr爲當前元素的數組對象,可省略
console.log(this); // {a: 2}
console.log(`索引:${index},元素:${value}`);
return value * this.a;
}, obj); // 方法能夠接受第二個參數,回調函數內部的this對象會指向第二個參數,不傳則爲當前環境的this
console.log(newArr); // [2, 4, 6]
console.log(arr); // [1, 2, 3]
複製代碼
forEach()
用於調用數組的每一個元素,並將元素傳遞給回調函數。
forEach()
不返回值,只用來操做數據,不會對空數組執行回調函數,不能使用break
和continue
,可使用return
。
var arr = [1, 2, 3];
var obj = {a: 2};
var sum = 0;
arr.forEach(function(value, index, arr) { // 參數同map()
console.log(`索引:${index},元素:${value}`);
console.log(this); // {a: 2}
sum += value;
}, obj); // 方法的第二個參數同map()
console.log(sum); // 6
複製代碼
filter
,過濾器,顧名思義,過濾掉指定數組不符合條件的元素,返回一個數組。若是沒有符合條件的元素則返回一個空數組。
不會對空數組進行檢測,也不會改變原數組,不能使用break
和continue
。
var arr = [1, 2, 3];
let newArr = arr.filter(function(value, index, arr){ // 參數同map()
console.log(`索引:${index},元素:${value}`);
return value > 2;
});
console.log(newArr); // [3]
複製代碼
some()
方法用於檢測數組中是否有元素知足指定條件,返回一個布爾值。
依次執行數組的每一個元素:若是有一個元素知足條件,就返回true
, 剩餘的元素不會再檢測;若是沒有知足條件的元素,則返回false
。
不會對空數組進行檢測,不會改變原始數組,不能使用break
和continue
。
var arr = [1, 2, 3];
var result = arr.some(function(value, index, arr) {
console.log(`索引:${index},元素:${value}`);
return value > 2;
});
console.log(result); // true
console.log(arr); // [1, 2, 3]
複製代碼
every()
和some()
相似,都是返回一個布爾值,可是要數組中的所有元素知足指定條件纔會返回true
,不然返回false
。
var arr = [1, 2, 3];
var result = arr.every(function(value, index, arr) {
console.log(`索引:${index},元素:${value}`);
return value > 2;
});
console.log(result); // false
console.log(arr); // [1, 2, 3]
複製代碼
reduce()
方法接收一個函數做爲累加器,數組中的每一個值按順序縮減(reduce),最終計算返回一個值。
reduceRight()
,顧名思義,順序是從右往左。
var arr = [1, 2, 3, 4];
var total = arr.reduce(function(total, value, index, arr) {
// 相對於map()方法,多了一個total參數,這個是初始值, 或者計算結束後的返回值。前兩個必填。
return total + value;
})
console.log(total); // 10
複製代碼
find()
方法返回數組符合條件的第一個元素的值,沒有符合的會返回undefined
。 findIndex()
方法返回返回數組符合條件的第一個元素的索引位置,若是沒有符合條件的則返回 -1
。
var arr = [1, 2, 3, 4];
var value = arr.find(function(value, index, arr) {
return value > 2;
})
console.log(value); // 3
var index = arr.findIndex(function(value, index, arr) {
return value > 2;
})
console.log(index); // 2
複製代碼
返回某個指定的字符串值在字符串中首次出現的位置,若是沒有找到匹配的字符串則返回 -1
。能夠用來判斷字符串中是否存在某個字符串。
有兩個參數:第一個參數爲須要檢索的字符串值,必填;第二個是開始檢索的位置,省略則從0
開始檢索。
var str = 'Hello world!';
var index = str.indexOf('w', 3); // 在第3個位置開始查找'w'第一次出現的位置
console.log(index); // 6
複製代碼
Object.keys()/Object.values()
都會返回一個數組,keys()
返回的是給定對象的全部可枚舉屬性的字符串數組,values()
返回的是對應值的數組。
var obj = { a: 1, b: 2,};
console.log(Object.keys(obj)); // ["a", "b"]
console.log(Object.values(obj)); // [1, 2]
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // ["0", "1", "2"]
console.log(Object.values(arr)); // ["a", "b", "c"]
複製代碼
使用return
會終止函數的執行並返回函數的值,若是忽略,將返回undefined
。
使用break
語句會跳出當前循環,繼續執行循環體後面的語句。若是有多層循環,break
只能跳出一層循環。
使用continue
語句會跳過循環中的一個迭代,繼續循環中的下一個迭代。
// return
function myReturn(){
for (var i = 0; i < 5; i++) {
if (i == 2) return i;
}
}
console.log(myReturn());
// break
for (var i = 0; i < 5; i++) {
if (i == 2) break;
console.log(i); // 0,1
}
// continue
for (var i = 0; i < 5; i++) {
if (i == 2) continue;
console.log(i); // 0,1,3,4
}
複製代碼