javascript中為何優先使用遍歷方法而非循環程式碼詳解
優先使用遍歷方法而非循環
在使用迴圈的時候,很容易違反DRY(Don't Repeat Yourself)原則。這是因為我們通常會選擇複製貼上的方法來避免手寫一段段落的循環語句。但是這樣做回讓程式碼中出現大量重複程式碼,開發人員也在沒有意義地」重複造輪子」。更重要的是,複製貼上的時候很容易忽略循環中的那些細節,例如起始索引值,終止判斷條件等。
例如以下的for迴圈就存在這個問題,假設n是集合物件的長度:
for (var i = 0; i <= n; i++) { ... } // 终止条件错误,应该是i < n for (var i = 1; i < n; i++) { ... } // 起始变量错误,应该是i = 0 for (var i = n; i >= 0; i--) { ... } // 起始变量错误,应该是i = n - 1 for (var i = n - 1; i > 0; i--) { ... } // 终止条件错误,应该是i >= 0
可見在迴圈的一些細節處理上很容易出錯。而利用JavaScript提供的閉包(參見Item 11),可以將循環的細節給封裝起來供重用。實際上,ES5就提供了一些方法來處理這個問題。其中的Array.prototype.forEach是最簡單的一個。利用它,我們可以將循環這樣寫:
// 使用for循环 for (var i = 0, n = players.length; i < n; i++) { players[i].score++; } // 使用forEach players.forEach(function(p) { p.score++; });
除了對集合物件進行遍歷之外,另一種常見的模式是對原始集合中的每個元素進行某種操作,然後得到一個新的集合,我們也可以利用forEach方法實現如下:
// 使用for循环 var trimmed = []; for (var i = 0, n = input.length; i < n; i++) { trimmed.push(input[i].trim()); } // 使用forEach var trimmed = []; input.forEach(function(s) { trimmed.push(s.trim()); });
但是由於這個由將一個集合轉換為另一個集合的模式十分常見,ES5也提供了Array.prototype.map方法用來讓程式碼更簡單、更優雅:
var trimmed = input.map(function(s) { return s.trim(); });
另外,還有一個常見模式是對集合根據某種條件進行過濾,然後得到一個原集合的子集。 ES5中提供了Array.prototype.filter來實現此模式。此方法接受一個Predicate作為參數,它是一個傳回true或false的函數:傳回true表示該元素會保留在新的集合中;傳回false則表示該元素不會出現在新集合中。例如,我們使用以下程式碼來對商品的價格進行過濾,僅保留價格在[min, max]區間的商品:
listings.filter(function(listing) { return listing.price >= min && listing.price <= max; });
當然,以上的方法是在支援ES5的環境中可用的。在其它環境中,我們有兩種選擇: 1. 使用第三方函式庫,如underscore或lodash,它們都提供了相當多的通用方法來操作物件和集合。 2. 根據需要自行定義。
例如,定義如下的方法來根據某個條件取得集合中前面的若干元素:
function takeWhile(a, pred) { var result = []; for (var i = 0, n = a.length; i < n; i++) { if (!pred(a[i], i)) { break; } result[i] = a[i]; } return result; } var prefix = takeWhile([1, 2, 4, 8, 16, 32], function(n) { return n < 10; }); // [1, 2, 4, 8]
為了更好的重用該方法,我們可以將它定義在Array.prototype物件上,具體的影響可以參考Item 42。
Array.prototype.takeWhile = function(pred) { var result = []; for (var i = 0, n = this.length; i < n; i++) { if (!pred(this[i], i)) { break; } result[i] = this[i]; } return result; }; var prefix = [1, 2, 4, 8, 16, 32].takeWhile(function(n) { return n < 10; }); // [1, 2, 4, 8]
只有一個場合使用迴圈會比使用遍歷函數好:需要使用break和continue的時候。 例如,當使用forEach來實作上面的takeWhile方法時就會有問題,在不滿足predicate的時候該如何實作呢?
function takeWhile(a, pred) { var result = []; a.forEach(function(x, i) { if (!pred(x)) { // ? } result[i] = x; }); return result; }
我們可以使用一個內部的異常來進行判斷,但是它同樣有些笨拙和低效:
function takeWhile(a, pred) { var result = []; var earlyExit = {}; // unique value signaling loop break try { a.forEach(function(x, i) { if (!pred(x)) { throw earlyExit; } result[i] = x; }); } catch (e) { if (e !== earlyExit) { // only catch earlyExit throw e; } } return result; }
可是使用forEach之後,程式碼甚至比使用它之前更加冗長。這顯然是存在問題的。 對於這個問題,ES5提供了some和every方法用來處理存在提前終止的循環,它們的用法如下所示:
[1, 10, 100].some(function(x) { return x > 5; }); // true [1, 10, 100].some(function(x) { return x < 0; }); // false [1, 2, 3, 4, 5].every(function(x) { return x > 0; }); // true [1, 2, 3, 4, 5].every(function(x) { return x < 3; }); // false
這兩個方法都是短路方法(Short-circuiting):只要有任何一個元素在some方法的predicate中回傳true,那麼some就會回傳;只有有任何一個元素在every方法的predicate中傳回false,那麼every方法也會回傳false。
因此,takeWhile就可以實現如下:
function takeWhile(a, pred) { var result = []; a.every(function(x, i) { if (!pred(x)) { return false; // break } result[i] = x; return true; // continue }); return result; }
實際上,這就是函數式程式設計的想法。在函數式程式設計中,你很少能夠看見明確的for迴圈或while迴圈。循環的細節都被很好地封裝起來了。
以上是javascript中為何優先使用遍歷方法而非循環程式碼詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

人臉偵測辨識技術已經是一個比較成熟且應用廣泛的技術。而目前最廣泛的網路應用語言非JS莫屬,在Web前端實現人臉偵測辨識相比後端的人臉辨識有優勢也有弱勢。優點包括減少網路互動、即時識別,大大縮短了使用者等待時間,提高了使用者體驗;弱勢是:受到模型大小限制,其中準確率也有限。如何在web端使用js實現人臉偵測呢?為了實現Web端人臉識別,需要熟悉相關的程式語言和技術,如JavaScript、HTML、CSS、WebRTC等。同時也需要掌握相關的電腦視覺和人工智慧技術。值得注意的是,由於Web端的計

股票分析必備工具:學習PHP和JS繪製蠟燭圖的步驟,需要具體程式碼範例隨著網路和科技的快速發展,股票交易已成為許多投資者的重要途徑之一。而股票分析是投資人決策的重要一環,其中蠟燭圖被廣泛應用於技術分析。學習如何使用PHP和JS繪製蠟燭圖將為投資者提供更多直觀的信息,幫助他們更好地做出決策。蠟燭圖是一種以蠟燭形狀來展示股票價格的技術圖表。它展示了股票價格的

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

Java是一種流行的程式語言,具有強大的檔案處理功能。在Java中,遍歷資料夾並取得所有檔案名稱是一種常見的操作,可以幫助我們快速定位和處理特定目錄下的檔案。本文將介紹如何在Java中實作遍歷資料夾並取得所有檔案名稱的方法,並提供具體的程式碼範例。 1.使用遞歸方法遍歷資料夾我們可以使用遞歸方法遍歷資料夾,遞歸方法是一種自身呼叫自身的方式,可以有效地遍歷資料夾中

隨著網路金融的快速發展,股票投資已經成為了越來越多人的選擇。而在股票交易中,蠟燭圖是常用的技術分析方法,它能夠顯示股票價格的變動趨勢,幫助投資人做出更精準的決策。本文將透過介紹PHP和JS的開發技巧,帶領讀者了解如何繪製股票蠟燭圖,並提供具體的程式碼範例。一、了解股票蠟燭圖在介紹如何繪製股票蠟燭圖之前,我們首先需要先了解什麼是蠟燭圖。蠟燭圖是由日本人

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

js和vue的關係:1、JS作為Web開發基石;2、Vue.js作為前端框架的崛起;3、JS與Vue的互補關係;4、JS與Vue的實踐應用。

JavaScript中的HTTP狀態碼取得方法簡介:在進行前端開發中,我們常常需要處理與後端介面的交互,而HTTP狀態碼就是其中非常重要的一部分。了解並取得HTTP狀態碼有助於我們更好地處理介面傳回的資料。本文將介紹使用JavaScript取得HTTP狀態碼的方法,並提供具體程式碼範例。一、什麼是HTTP狀態碼HTTP狀態碼是指當瀏覽器向伺服器發起請求時,服務
