Javascript 循環和迭代

循環

在Javascript中數組循環使用for循環,跟其他的語言非常類似。

//數組循環
var array = [1,2,3,4,5];
for(var i = 0; i < array.length; i++){
    console.log(array[i]);
}

//對象循環
var obj = {a:1,b:2,c:3};
for(var i in obj){
    console.log(i+':'+obj[i]);
}

迭代

在ES5中新增了幾種迭代方法(forEach, every, filter, map, some)。根據文檔顯示,這些方法都含有兩個參數:

callback

    爲數組中每個元素執行的函數,該函數接收三個參數:

    currentValue(當前值)

        數組中正在處理的當前元素。

    index(索引)

        數組中正在處理的當前元素的索引。

    array

        方法正在操作的數組。

thisArg可選

    可選參數。當執行回調 函數時用作this的值(參考對象)。

 

forEach

循環遍歷數組。forEach 方法按升序爲數組中含有效值的每一項執行一次callback 函數,那些已刪除(使用delete方法等情況)或者未初始化的項將被跳過(但不包括那些值爲 undefined 的項)。

forEach 遍歷的範圍在第一次調用 callback 前就會確定。調用forEach 後添加到數組中的項不會被 callback 訪問到。如果已經存在的值被改變,則傳遞給 callback 的值是 forEach 遍歷到他們那一刻的值。已刪除的項不會被遍歷到。如果已訪問的元素在迭代時被刪除了(例如使用 shift()) ,之後的元素將被跳過 。

forEach() 爲每個數組元素執行callback函數;不像 map() 或者 reduce() ,它總是返回 undefined 值,並且不可鏈式調用。典型用例是在一個鏈的最後執行副作用。

沒有辦法中止或者跳出 forEach 循環,除了拋出一個異常。如果你需要這樣,使用forEach()方法是錯誤的,你可以用一個簡單的循環作爲替代。

簡單使用

下面的代碼會爲每一個數組元素輸出一行記錄:

function logArrayElements(element, index, array) {
    console.log("a[" + index + "] = " + element);
}

// 注意索引2被跳過了,因爲在數組的這個位置沒有項
[2, 5, ,9].forEach(logArrayElements);

// a[0] = 2
// a[1] = 5
// a[3] = 9

[2, 5,"" ,9].forEach(logArrayElements);
// a[0] = 2
// a[1] = 5
// a[2] = 
// a[3] = 9

[2, 5, undefined ,9].forEach(logArrayElements);
// a[0] = 2
// a[1] = 5
// a[2] = undefined
// a[3] = 9


let xxx;
// undefined

[2, 5, xxx ,9].forEach(logArrayElements);
// a[0] = 2
// a[1] = 5
// a[2] = undefined
// a[3] = 9

使用thisArg

從每個數組中的元素值中更新一個對象的屬性:

function Counter() {
    this.sum = 0;
    this.count = 0;
}

Counter.prototype.add = function(array) {
    array.forEach(function(entry) {
        this.sum += entry;
        ++this.count;
    }, this);
    //console.log(this);
};

var obj = new Counter();
obj.add([1, 3, 5, 7]);

obj.count; 
// 4 === (1+1+1+1)
obj.sum;
// 16 === (1+3+5+7)

如果數組在迭代時被修改了,則其他元素會被跳過

下面的例子輸出"one", "two", "four"。當到達包含值"two"的項時,整個數組的第一個項被移除了,這導致所有剩下的項上移一個位置。因爲元素 "four"現在在數組更前的位置,"three"會被跳過。 forEach()不會在迭代之前創建數組的副本。

var words = ["one", "two", "three", "four"];
words.forEach(function(word) {
  console.log(word);
  if (word === "two") {
    words.shift();
  }
});
// one
// two
// four

 

every

測試數組中所有元素是否都通過指定函數的測試,若有一項終止並返回false。

every 方法爲數組中的每個元素執行一次 callback 函數,直到它找到一個使 callback 返回 false(表示可轉換爲布爾值 false 的值)的元素。如果發現了一個這樣的元素,every 方法將會立即返回 false。否則,callback 爲每一個元素返回 trueevery 就會返回 truecallback 只會爲那些已經被賦值的索引調用。不會爲那些被刪除或從來沒被賦值的索引調用。

every 不會改變原數組。

every 遍歷的元素範圍在第一次調用 callback 之前就已確定了。在調用 every 之後添加到數組中的元素不會被 callback 訪問到。如果數組中存在的元素被更改,則他們傳入 callback 的值是 every 訪問到他們那一刻的值。那些被刪除的元素或從來未被賦值的元素將不會被訪問到。

every 和數學中的"所有"類似,當所有的元素都符合條件才返回true。另外,空數組也是返回true。(空數組中所有元素都符合給定的條件,注:因爲空數組沒有元素)。

檢測所有數組元素的大小

檢測數組中的所有元素是否都大於 10。

function isBigEnough(element, index, array) {
  return (element >= 10);
}
var passed = [12, 5, 8, 130, 44].every(isBigEnough);
// passed is false
passed = [12, 54, 18, 130, 44].every(isBigEnough);
// passed is true
var a = [1, 2, 3,, 4].every (function(value){
console.log(value)
   return value       
})//1,2,3,4
console.log(a)//true
a = [1, 2, 3, undefined,4].every (function(value){
console.log(value)
   return value       
})//1,2,3,undefind
console.log(a)//false

 

filter

使用指定的函數測試所有的元素,創建並返回一個包含所有通過測試的元素的新數組。如果沒有通過測試則返回空數組。

filter 爲數組中的每個元素調用一次 callback 函數,並利用所有使得 callback 返回 true 或等價於 true 的值的元素創建一個新數組。callback 只會在已經賦值的索引上被調用,對於那些已經被刪除或者從未被賦值的索引不會被調用。那些沒有通過 callback 測試的元素會被跳過,不會被包含在新數組中。

filter 不會改變原數組,它返回過濾後的新數組。

filter 遍歷的元素範圍在第一次調用 callback 之前就已經確定了。在調用 filter 之後被添加到數組中的元素不會被 filter 遍歷到。如果已經存在的元素被改變了,則他們傳入 callback 的值是 filter 遍歷到它們那一刻的值。被刪除或從來未被賦值的元素不會被遍歷到。

使用 filter 創建了一個新數組,該數組的元素由原數組中值大於 10 的元素組成。

var a = [1, 2, 3, 7,4].filter(function(value){
   return value > 4      
})
console.log(a)//[7]

function isBigEnough(element) {
  return element >= 10;
}
var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// filtered is [12, 130, 44]

 

map

爲數組每一項(不包括通過某些方法刪除或者未定義的項,值定義爲undefined的項除外)執行一個指定函數,返回一個新數組,每個元素都是回調函數的結果。

map 方法會給原數組中的每個元素都按順序調用一次  callback 函數。callback 每次執行後的返回值(包括 undefined )組合起來形成一個新數組。 callback 函數只會在有值的索引上被調用;那些從來沒被賦過值或者使用 delete 刪除的索引則不會被調用。

map 不修改調用它的原數組本身(當然可以在 callback 執行時改變原數組)。

使用 map 方法處理數組時,數組元素的範圍是在 callback 方法第一次調用之前就已經確定了。在 map 方法執行的過程中:原數組中新增加的元素將不會被 callback 訪問到;若已經存在的元素被改變或刪除了,則它們的傳遞到 callback 的值是 map 方法遍歷到它們的那一時刻的值;而被刪除的元素將不會被訪問到。

下面的代碼創建了一個新數組,值爲原數組中對應數字的平方根:

var numbers = [1, 4, 9];
var roots = numbers.map(Math.sqrt);
// roots的值爲[1, 2, 3], numbers的值仍爲[1, 4, 9]

使用 map 重新格式化數組中的對象

以下代碼將一個包含對象的數組用以創建一個包含新重新格式化對象的新數組。

var kvArray = [{key: 1, value: 10}, 
               {key: 2, value: 20}, 
               {key: 3, value: 30}];

var reformattedArray = kvArray.map(function(obj) { 
   var rObj = {};
   rObj[obj.key] = obj.value;
   return rObj;
});

// reformattedArray 數組爲: [{1: 10}, {2: 20}, {3: 30}], 

// kvArray 數組未被修改: 
// [{key: 1, value: 10}, 
//  {key: 2, value: 20}, 
//  {key: 3, value: 30}]

 

some

測試數組中某些元素是否通過指定函數的測試,若有一項終止循環返回true。

some 爲數組中的每一個元素執行一次 callback 函數,直到找到一個使得 callback 返回一個“真值”(即可轉換爲布爾值 true 的值)。如果找到了這樣一個值,some 將會立即返回 true。否則,some 返回 falsecallback 只會在那些”有值“的索引上被調用,不會在那些被刪除或從來未被賦值的索引上調用。

some 被調用時不會改變數組。

some 遍歷的元素的範圍在第一次調用 callback. 時就已經確定了。在調用 some 後被添加到數組中的值不會被 callback 訪問到。如果數組中存在且還未被訪問到的元素被 callback改變了,則其傳遞給 callback 的值是 some 訪問到它那一刻的值。

測試數組元素的值

下面的例子檢測在數組中是否有元素大於 10。

function isBiggerThan10(element, index, array) {
  return element > 10;
}

[2, 5, 8, 1, 4].some(isBiggerThan10);  // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true

使用箭頭函數測試數組元素的值

[2, 5, 8, 1, 4].some(x => x > 10);  // false
[12, 5, 8, 1, 4].some(x => x > 10); // true

判斷數組元素中是否存在某個值

var fruits = ['apple', 'banana', 'mango', 'guava'];

function checkAvailability(arr, val) {
  return arr.some(function(arrVal) {
    return val === arrVal;
  });
}

checkAvailability(fruits, 'kela');   // false
checkAvailability(fruits, 'banana'); // true

將任意值轉換爲布爾類型

var TRUTHY_VALUES = [true, 'true', 1];

function getBoolean(value) {
  'use strict';
   
  if (typeof value === 'string') { 
    value = value.toLowerCase().trim();
  }

  return TRUTHY_VALUES.some(function(t) {
    return t === value;
  });
}

getBoolean(false);   // false
getBoolean('false'); // false
getBoolean(1);       // true
getBoolean('true');  // true

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章