整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          JS遍歷數組

          JavaScript 作為 Web 開發的核心語言之一,在前端領域發揮著至關重要的作用。數組作為 JavaScript 中最常用的數據結構之一,掌握其遍歷方法對于任何前端開發者都是必不可少的技能。本文旨在介紹幾種常見的數組遍歷方式,并通過實例演示它們的應用場景和最佳實踐。

          技術概述

          定義

          數組遍歷是指按照一定的順序訪問數組中的每一個元素的過程。JavaScript 提供了多種方法來遍歷數組,包括傳統的 for 循環、forEach 方法、mapfilter 等高階函數。

          核心特性與優勢

          • 傳統 `for` 循環:
          • 特性: 直接訪問索引。
          • 優勢: 靈活性高,可以控制循環的終止條件。
          • `forEach` 方法:
          • 特性: 自動迭代數組中的每個元素。
          • 優勢: 代碼簡潔,易于理解和維護。
          • `map` 方法:
          • 特性: 創建新數組,對原數組每個元素執行函數并返回新值。
          • 優勢: 方便轉換數據結構。
          • `filter` 方法:
          • 特性: 創建新數組,包含通過測試的所有元素。
          • 優勢: 用于篩選數據。

          示例代碼

          const numbers = [1, 2, 3, 4, 5];
          
          // 使用 for 循環
          for (let i = 0; i < numbers.length; i++) {
            console.log(numbers[i]);
          }
          
          // 使用 forEach
          numbers.forEach(function(number) {
            console.log(number);
          });
          
          // 使用 map
          const doubled = numbers.map(function(number) {
            return number * 2;
          });
          console.log(doubled);
          
          // 使用 filter
          const evenNumbers = numbers.filter(function(number) {
            return number % 2 === 0;
          });
          console.log(evenNumbers);
          

          技術細節

          遍歷原理

          數組遍歷的基本原理是按照一定的順序訪問數組中的每個元素。不同的遍歷方法內部實現有所不同,但最終目的是相同的。

          • `for` 循環:
          • 原理: 通過索引直接訪問數組元素。
          • 注意事項: 索引越界問題。
          • `forEach` 方法:
          • 原理: 內部使用迭代器模式。
          • 注意事項: 無法中斷遍歷過程。
          • `map` 方法:
          • 原理: 對每個元素應用函數并返回新數組。
          • 注意事項: 不改變原數組。
          • `filter` 方法:
          • 原理: 對每個元素應用函數判斷是否保留。
          • 注意事項: 同樣不改變原數組。

          難點

          • 中斷遍歷: forEach 方法不能直接使用 breakreturn 中斷遍歷。
          • 性能考慮: mapfilter 返回新數組,可能導致內存消耗增加。

          實戰應用

          場景與案例

          假設我們需要從一個數組中找出所有的偶數,并計算這些偶數的平方。

          問題與解決方案

          問題: 如何高效地找到所有偶數并計算它們的平方?

          解決方案: 使用 filter 方法篩選出偶數,再使用 map 方法計算平方。

          示例代碼

          const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
          
          // 使用 filter 和 map
          const evenSquares = numbers
            .filter(number => number % 2 === 0)
            .map(number => number * number);
          
          console.log(evenSquares); // 輸出: [4, 16, 36, 64, 100]
          

          優化與改進

          潛在問題

          • 性能: 在大數據量下使用 mapfilter 可能導致性能下降。
          • 內存: 過多使用高階函數可能會增加內存占用。

          優化建議

          • 減少循環次數: 嘗試合并操作以減少循環次數。
          • 使用緩存: 如果結果不變,可以緩存結果以減少重復計算。

          示例代碼

          // 緩存結果
          const cache = {};
          
          function getEvenSquares(numbers) {
            if (cache[numbers]) {
              return cache[numbers];
            }
          
            const result = numbers
              .filter(number => number % 2 === 0)
              .map(number => number * number);
          
            cache[numbers] = result;
          
            return result;
          }
          

          常見問題

          問題及解決

          問題: 如何在 forEach 中中斷循環?

          解決方案: 使用 for 循環或 Array.prototype.some() 方法。

          // 使用 some
          const numbers = [1, 2, 3, 4, 5];
          let found = false;
          
          numbers.some(function(number) {
            if (number > 3) {
              found = true;
              return true; // 終止循環
            }
          });
          
          console.log(found); // 輸出: true
          

          總結與展望

          通過本文的學習,我們了解了 JavaScript 數組遍歷的多種方法及其應用場景。每種方法都有其特點和適用場合,合理選擇可以提高代碼的效率和可讀性。隨著 JavaScript 語言的發展,新的遍歷方法和優化技巧會不斷出現,我們期待未來能有更多實用高效的工具和技術出現,以進一步提升前端開發的效率和質量。

          希望本文能為你在實際開發中遇到的問題提供一些解決方案和思路,同時也鼓勵你不斷學習新的技術和方法,以應對日益復雜的前端開發挑戰。

          、for...in 語句


          1.1 遍歷對象屬性名稱

          for...in 語句常用于遍歷特定對象的屬性,包括字段名稱屬性及函數名稱屬性。在JavaScript語言中,它們均稱為屬性 (property)。

          let obj = {
            name: 'obj',
          
            showName() {
              console.log(this.name);
            }
          };
          
          for (const propName in obj) {
            console.log(propName, typeof(obj[propName]));
          }

          顯示:

          name – "string"
          showName – "function"

          利用這一點,可方便地查看特定對象的所有屬性或方法名稱。下面語句打印出console對象所有的屬性:

          for (const propName in console) {
            console.log(propName, typeof(console[propName]));
          }

          顯示:

          debug – "function"
          error – "function"
          log – "function"
          info – "function"
          warn – "function"
          clear – "function"
          ...

          可以看出,這些屬性全部均是console的函數名稱,因為console沒有屬性名稱。

          1.2 遍歷數組索引值

          for...in 用于數組中,則遍歷數組索引值。

          let array = ['a', 'b', 'c'];
          
          for (const index in array) {
            console.log(index, array[index]);
          }

          顯示:

          0 – "a"
          1 – "b"
          2 – "c"

          1.3 遍歷字符串索引值

          由于字符串是由字符組成的數組,因此 for...in 也可用于遍歷字符串的索引值。

          let str = "abc";
          
          for (const index in str) {
            console.log(index, str[index]);
          }

          顯示:

          0 – "a"
          1 – "b"
          2 – "c"

          2、for...of 語句


          for...of 語句用于遍歷可遍歷對象 (iterable objects)的元素。這些可遍歷對象包括字符串、數組、以及類似于數組的對象,這些對象都帶有length屬性。

          2.1 不能用于遍歷對象屬性名稱

          for...of 語句不能用于遍歷對象的屬性名稱。因此,下面的代碼是錯誤的:

          let obj = {
            name: 'obj',
          
            showName() {
              console.log(this.name);
            }
          };
          
          for (const propName of obj) {
            console.log(propName);
          }

          顯示:

          TypeError: undefined is not a function (near '...propName of obj...')

          意為,將 for...of 語句用于對象上面,無法提取具體的數值。

          2.2 遍歷數組元素

          for...of 語句經常用于遍歷數組中各元素的數值。

          let arr = [2, 4, 6, 8, 10];
          
          for (const value of arr) {
            console.log(value);
          }

          顯示:

          2
          4
          6
          8
          10

          2.3 遍歷字符串中的字符

          由于字符串是由字符組成的數組,因此 for...of 也可用于遍歷字符串的字符。

          let str = "abc";
          
          for (const letter of str) {
            console.log(letter);
          }

          顯示:

          a
          b
          c

          2.4 解包

          數組元素如果是帶有特定屬性名稱的對象,可利用解包性質來快速遍歷這些屬性值。看下面例子。

          function Point(x, y) {
            return {x:x, y:y};
          }
          
          let points = [Point(1, 2), Point(2, 3), Point(4, 5)];
          
          for (const point of points) {
            console.log(point.x, point.y);
          }
          

          可將Point視為一個構造器 (constructor),每次調用Point(x, y)都會創建并返回該類的一個對象,且含有x及y的屬性名稱。points則是一個含有多個Point對象的數組。上面的代碼遍歷出每個Point對象后,賦值于point變量,然后打印出它們的x值及y值。

          如果我們不希望每次都通過引用對象屬性的方式來訪問x及y值,則可編寫代碼如下:

          for (const point of points) {
            let x = point.x;
            let y = point.y;
            console.log(x, y);
          }

          這一步可利用ES6的const解包特性予以簡化:

          for (const point of points) {
            const {x, y} = point;
            console.log(x, y);
          }

          更進一步,我們可以直接解包:

          for (const {x, y} of points) {
            console.log(x, y);
          }

          2.5 遍歷Map

          let scoreMap = new Map([
              ['Mike', 75],
              ['Tom', 80],
              ['Smith', 90]
          ]);
          
          for (const [key, value] of scoreMap) {
              console.log(key, value);
          }

          與上一節不同的是,Map需要使用 [key, value] 的方式來解包。

          3、forEach 方法


          3.1 forEach 常見調用方式

          for...in,for...of 均是語句,與它們不同的是,forEach是數組的內嵌方法。這意味著我們可以直接在數組對象上面直接調用該方法。

          let arr = [1, 3, 5, 7, 9];
          
          arr.forEach((element) => {
            console.log(element);
          });

          作為數組方法,forEach有一個參數,該參數的類型是函數,稱為回調函數 (callback function)。所謂回調函數,是指一旦程序員提供了這樣的函數,JavaScript引擎將負責調用此函數。

          回調函數的價值在于回調函數可能存在多個參數,而這些參數將由JavaScript引擎自動提供。在回調函數中,我們可對JavaScript引擎所自動提供的參數進行進一步加工。

          在上面的回調函數中,element是由JavaScript引擎自動提供的,代表每個數組元素。

          上面的代碼采用了lambda匿名表達式。它等同于:

          let arr = [1, 3, 5, 7, 9];
          
          function callback(element) {
            console.log(element);
          }
          
          arr.forEach(callback);

          可見,lambda表達式更加簡練。

          3.2 forEach 的參數

          forEach共有3個參數 (上面例子只用了第1個),它們的排列順序如下:

          arr.forEach((element, index, array) => {
            console.log(element);
            console.log(index);
            console.log(array);
          });

          參數element是數組元素,參數index是數組元素所在數組中的索引值,參數array是整個數組。

          一般情況下,我們僅需用到element及index參數就足夠了。由于是每次迭代,因此,forEach方法中的array參數較少用到。

          index每次遍歷時都會加1,且每次都會與array的長度比較。一旦超出array的界限,就會終止遍歷。如果遍歷過程中,修改了array的長度,則需特別注意這一點。

          3.2 forEach 遍歷的終止

          如何中止forEach的遍歷?JavaScript并未提供這樣的機制,但我們可以用一個雙重嵌套的異常來終止遍歷。

          let arr = [1, 3, 5, 7, 9];
          
          try {
            arr.forEach((element, index, array) => {
              try {
                console.log(index);
                if (index >= 3) {
                  throw new Error('forEach termination signal');
                }
              } catch (error) {
                throw error;
              }
            });
          } catch (e) {
            if (e.message === 'forEach termination signal') {
              console.log('forEach terminated.');
            }
          }
          
          console.log('This line of code should be executed.');

          顯示:

          0
          1
          2
          3
          forEach terminated.
          This line of code should be executed.

          我們設定,當index的值大于等于3時,需要終止遍歷。這樣,在第7行,當此條件滿足時,即拋出"forEach termination signal"的異常。

          此時,程序流程轉入到第10行至第12行最內層的異常捕獲處理代碼:

          } catch (error) {
              throw error;
          }

          捕獲異常后,如果我們不重新拋出異常,JavaScript引擎則會認為我們已正確地處理了異常,因此會恢復中斷的遍歷進程,繼續處理下一個數組元素,這不是我們想要的。因此,我們在此重新拋出該異常,以切實終止遍歷。

          這時,forEach的遍歷因異常而終止,從而達到了我們的最初的目標。但因為有異常,如果我們未作任何處理,則該異常會導致整個程序都終止運行。只有在我們處理了異常后,程序才能往下走。這就是第14行至18行最外層異常捕獲代碼的作用:

          } catch (e) {
            if (e.message === 'forEach termination signal') {
              console.log('forEach terminated');
            }
          }

          先判斷它是不是"forEach termination signal"。如果是,則簡單地打印一行消息。由于這里未再拋出新的異常,因此JavaScript引擎認為我們已經正確地處理了異常,則繼續執行后面的代碼。這樣,最后一行第20行語句將被執行并打印出"This line of code should be executed."的文本。

          一般來講,如果我們需要在數組的遍歷過程中終止遍歷,不要使用 forEach 語句,使用最傳統的方式即可:

          let arr = [1, 3, 5, 7, 9];
          
          for (let i = 0; i < arr.length; i++) {
            console.log(i, arr[i]);
            if (i >= 3) {
              break;
            }
          }
          
          console.log('This line of code should be executed.');

          這樣即可在遍歷中訪問數組的索引值與數組元素,又可以極為方便地隨時終止遍歷。

          歷數組是任何一門語言必不可少的功能,本文主要介紹JavaScript中遍歷數組的各種方法。

          首先定義一個數組,如下圖所示:

          1、every函數:

          arr.every(callback(currentValue, index, array)[, thisArg])

          測試數組的所有元素是否都通過了指定函數的測試

          callback 用來測試每個元素的函數。

          thisArg 可選,如果為 every 提供一個 thisArg 參數,在該參數為調用 callback 時的 this 值。如果省略該參數,則 callback 被調用時的 this 值,在非嚴格模式下為全局對象,在嚴格模式下傳入 undefined。

          currentValue:元素值,index:元素的索引,array:原數組

          every 不會改變原數組。當callback函數返回false時,循環結束,示例如下:

          打印結果如下:

          2、some函數:

          arr.some(callback(currentValue, index, array)[, thisArg])

          currentValue:元素值,index:元素的索引,array:原數組

          some 不會改變原數組。與every不通的是,當callback函數返回true時,循環結束,示例如下:

          打印結果如下:

          3、forEach函數:

          arr.forEach(callback(currentValue, index, array)[, thisArg])

          為每個元素都執行callback函數,直接修改原數組,沒有返回值,循環過程中不能停止,示例如下:

          打印結果如下:

          4、map函數:

          arr.map(callback (currentValue, index, array)[, thisArg])

          返回一個經過處理的新數組,不會破壞原來的數組,需要注意的是callback函數里面需要返回currentValue,也就是說map是通過每次循環返回的值作為元素組成新數組的,并且在循環過程中不能停止,示例如下:

          打印結果如下:

          5、filter函數:

          arr.filter(callback (element, index, arrArg)[, thisArg])

          對數組中的每個元素都執行一次指定的函數(callback),并且創建一個新的數組,該數組元素是所有回調函數執行時返回值為 true 的原數組元素。示例如下:

          打印結果如下:

          6、reduce函數:

          arr.reduce(callback(accumulator, currentValue, currentIndex, array), initialValue)

          方法對累加器和數組中的每個元素 (從左到右)應用一個函數,將其減少為單個值,返回函數累計處理的結果。

          參數說明:

          callback:執行數組中每個值的函數,包含四個參數

          accumulator 上一次調用回調返回的值,或者是提供的初始值(initialValue)

          currentValue 數組中正在處理的元素

          currentIndex 數據中正在處理的元素索引,如果提供了 initialValue ,從0開始;否則從1開始

          initialValue 可選項,其值用于第一次調用 callback 的第一個參數。如果沒有設置初始值,則將數組中的第一個元素作為初始值。空數組調用reduce時沒有設置初始值將會報錯。示例如下:

          打印結果如下:

          7、for循環:

          for循環是使用頻率較高的方法,效率也較高。數據量較大時,建議用此種方法。它可以通過break語句跳出循環,也可以通過continue語句跳過當前循環,示例如下:

          打印結果如下:

          需要注意的是for循環里面不支持return語句,如下寫法會報錯:

          打印結果如下:

          for方法還有兩種變體如下,但是效率不高:

          這種方式效率最低

          需要ES6支持,性能要好于forin,但仍然比不上普通for循環

          js數組遍歷函數雖然比較多,但各有各的用途,還希望大家在寫項目代碼的過程中多多嘗試一下。如果不知選哪個,或者比較注重效率的話,最佳的選擇還是普通for循環。


          主站蜘蛛池模板: 精品国产天堂综合一区在线| 亚洲AV成人一区二区三区在线看 | 亚洲av成人一区二区三区在线播放| 丰满爆乳无码一区二区三区 | 国产日韩精品一区二区在线观看播放| 亚洲色精品aⅴ一区区三区| 日本高清一区二区三区| 亚洲午夜精品一区二区公牛电影院 | 中文字幕人妻丝袜乱一区三区 | 国产精品亚洲不卡一区二区三区| 一区二区三区在线观看| 久久久国产精品亚洲一区 | 国产精品资源一区二区| 国产午夜精品一区二区三区极品 | 高清精品一区二区三区一区| 激情内射亚洲一区二区三区| 色狠狠AV一区二区三区| 亚洲av无码一区二区乱子伦as | 亚洲AV噜噜一区二区三区| 国产福利一区二区三区视频在线| 人体内射精一区二区三区| 无码国产精成人午夜视频一区二区 | 国产乱码一区二区三区| 亚洲av乱码中文一区二区三区| 九九无码人妻一区二区三区| 亚洲精品国产suv一区88| 精品人妻无码一区二区色欲产成人| 精品国产一区二区三区无码| 日韩一区二区三区四区不卡| 无码aⅴ精品一区二区三区| 国产精品一区二区资源| 亚洲av片一区二区三区| 国产波霸爆乳一区二区| 无码精品人妻一区二区三区人妻斩| 亚洲高清美女一区二区三区| 成人免费视频一区二区三区| 天天看高清无码一区二区三区| 激情综合一区二区三区| 一区二区三区福利视频免费观看| 国产精品亚洲一区二区麻豆| 日韩精品无码人妻一区二区三区 |