摘要:遞歸函數(shù)還會受到瀏覽器調(diào)用棧的大小的限制。雖然迭代也會導致性能問題,但是使用優(yōu)化的循環(huán)就可以代替長時間運行的遞歸函數(shù),可以提高新能,因為運行一個循環(huán)比反復調(diào)用一個函數(shù)的開銷要小。
本文章記錄本人在深入學習js循環(huán)中看書理解到的一些東西,加深記憶和并且整理記錄下來,方便之后的復習。
選擇正確的循環(huán)體在大部分編程語言中,代碼執(zhí)行的時間多數(shù)消耗在循環(huán)的執(zhí)行上。
js定義了4種類型的循環(huán):for, while, do while, for in。
for循環(huán)是最常用的循環(huán)結(jié)構(gòu),它由四個部分組成:
初始化體
前測條件
后執(zhí)行條件
循環(huán)體。
當遇到一個for循環(huán)的時候,初始化體首先執(zhí)行,然后進入前測條件。如果前測條件的計算為true,就會執(zhí)行循環(huán)體,然后運行后執(zhí)行條件。
Javascriptfor (var i = 0; i < 10; i++) { // 循環(huán)體 };
while循環(huán)是一個簡單的前測循環(huán),由一個前測條件和一個循環(huán)體構(gòu)成。在執(zhí)行循環(huán)體之前,先對前測條件進行計算。如果為true就執(zhí)行循環(huán)體。否則就會跳過循環(huán)體。
Javascriptvar i = 1; while (i < 10) { // 循環(huán)體 i ++; };
do while循環(huán)是js中唯一的一種后測試的循環(huán),它包括兩個部分:循環(huán)體和后側(cè)條件。記住:在一個do while循環(huán)中,循環(huán)體至少會運行一次,后測條件決定循環(huán)體是否再次運行。
Javascriptvar i = 1; do { // 循環(huán)體 } while (i++ < 10)
for in循環(huán)有一個非常特殊的用途:可以枚舉任何對象的命名函數(shù)屬性。
Javascriptfor (var attr in object) { // 循環(huán)體 };
每一次循環(huán),屬性都會被對象的屬性的名字(一個字符串)填充,直到所有的對象屬性遍歷完才會返回。返回的屬性包括對象的使實例屬性和對象從原型鏈基礎來的屬性。
想要提高循環(huán)性能,第一步選用哪種循環(huán)。在這四個循環(huán)里面,for in循環(huán)執(zhí)行的速度都比其他三個循環(huán)要慢。
比較 for 和 while大部分情況下我們都不會采用for in循環(huán),但是其他的循環(huán)類型性能都相當,難以確定哪種循環(huán)執(zhí)行速度更快。選擇循環(huán)類型應該基于需求而不是性能。
可以通過設計for和while循環(huán)來完成特定動作的重復性操作。從3個目標來分析如何正確的選用for和while循環(huán)。
語義角度比較
for和while循環(huán)可以按照下面的模式來進行互相的轉(zhuǎn)換。
Javascriptfor (initialization; test; increment) // 聲明并且初始化循環(huán)變量,循環(huán)條件,遞增循環(huán)變量 statements // 可執(zhí)行的循環(huán)語句
相當于:
Javascriptinitialization // 聲明并且初始化循環(huán)變量 while (test) { // 循環(huán)條件 statements // 可執(zhí)行的循環(huán)語句 increment // 遞增循環(huán)變量 }
for循環(huán)是以循環(huán)變量的變化來控制循環(huán)進程的,即for循環(huán)流程是預先計劃好的,雖然中途可能會因存在異常情況或特別情況而退出循環(huán),但是循環(huán)的規(guī)律是有章可循的。這樣的話就方便預知循環(huán)的次數(shù)和每次循環(huán)的狀態(tài)信息等等。
while循環(huán)根據(jù)特定條件來決定循環(huán)操作,由于條件是動態(tài)的,無法預知條件幾時是true或者false,因此該循環(huán)操作就具有很大的不確定性,每一次循環(huán)時都不知道下一次循環(huán)狀態(tài)如何,只能通過條件的變化來確定。
所以for循環(huán)通常用于有規(guī)律的重復操作中。while循環(huán)通常用于特定條件的重復操作,以及依據(jù)特定事件控制的循環(huán)等操作。
思維模式角度比較
for循環(huán)和while循環(huán)在思維模式上也存在差異。
for循環(huán)中,將循環(huán)的三個要素(起始值、終止值和步長)定義為3個基本表達式作為結(jié)構(gòu)語法的一部分固定在for語句里面,使用小括號;進行語法分隔,這樣有利于js的進行快速預編譯。
在閱讀到for循環(huán)結(jié)構(gòu)的第一行代碼的時候,就能夠獲取到整個循環(huán)結(jié)構(gòu)的控制方式,然后再根據(jù)上面的表達式來決定是否執(zhí)行循環(huán)體內(nèi)的語句。
Javascriptfor (var i = 0; i < 10; i++) { alert(i); };
可以按照下面的邏輯思維進行總結(jié):
執(zhí)行循環(huán)條件:1 < i < 10、步長為i++。
執(zhí)行循環(huán)語句:alert(i);。
這種把循環(huán)操作的環(huán)境條件和循環(huán)操作語句分離開的設計能夠提高程序的執(zhí)行效率,同時能夠避免因為把循環(huán)條件與循環(huán)語句混合在一起而造成的錯誤。
在for循環(huán)的特異性導致在執(zhí)行復雜的條件時效率會大大的降低。相對而言,while循環(huán)就比較適合運http://naotu.baidu.com/viewshare.html?shareId=auuohz8fwm8k的條件,它將復雜的循環(huán)控制放在循環(huán)體內(nèi)執(zhí)行,而while語句自身僅用于測試循環(huán)條件,這樣就避免了結(jié)構(gòu)的分隔和邏輯的跳躍。
Javascriptvar a = true, b = 1; while (a) { // 在循環(huán)體內(nèi)間接計算迭代 if (9 < b) { a = false; } alert(b); b++; }
從達到目標的角度比較
有一些循環(huán)的循環(huán)次數(shù)在循環(huán)之前就可以先預測,如計算1到100的數(shù)字和。而有一些循環(huán)具有不可預測性們無法事前確定循環(huán)的次數(shù),甚至無法預知循環(huán)操作的趨向,這些構(gòu)成了在設計循環(huán)結(jié)構(gòu)時候必須考慮的達成目標需要解決的問題,即使是相同的操作,如果達到的目標的角度不同,可能重復了操作的設計也就不同。
使用遞歸許多復雜的算法都是通過比較容易實現(xiàn)的遞歸實現(xiàn)。如階乘函數(shù)。
Javascriptfunction factorial(n) { if (0 === n) { return 1; } else { return n * factorial(n - 1); } };
遞歸函數(shù)的問題:錯誤定義或者缺少終結(jié)條件會導致函數(shù)運行時間過長,使瀏覽器出現(xiàn)假死現(xiàn)象。遞歸函數(shù)還會受到瀏覽器調(diào)用棧的大小的限制。
在ES6中js擁有了尾遞歸優(yōu)化,詳情請看迎接ECMAScript 6, 使用尾遞歸
使用迭代可以通過遞歸函數(shù)實現(xiàn)的算法都可以通過迭代來實現(xiàn)。迭代算法通常包括幾個不同的循環(huán),分別對應算法過程中的不同方面。雖然迭代也會導致性能問題,但是使用優(yōu)化的循環(huán)就可以代替長時間運行的遞歸函數(shù),可以提高新能,因為運行一個循環(huán)比反復調(diào)用一個函數(shù)的開銷要小。
使用迭代來實現(xiàn)合并排序算法:
Javascriptfunction merge(left, right) { var result = []; while (left.length > 0 && right.length > 0) { if (left[0] < right[0]) { result.push(left.shift()); } else { result.push(right.shift()); } } return result.concat(left).concat(right); }; function mergeSort(items) { if (items.length === 1) { return items; } var work = []; for (var i = 0, len = items.length; i < len; i++) { work.push(items[i]); }; work.push([]); for (var lim = len; lim > 1; lim = (lim + 1) / 2) { for (var j = 0, k = 0; k < lim; j++, k += 2) { work[j] = merge(work[k], work[k + 1]); } work[j] = []; }; return work[0]; };優(yōu)化循環(huán)結(jié)構(gòu)
循環(huán)結(jié)構(gòu)是最浪費資源的一種流程。循環(huán)結(jié)構(gòu)中的一點小的損耗都會被放大,從而影響程序運行的效率。
優(yōu)化結(jié)構(gòu)
循環(huán)結(jié)構(gòu)常常是與分支結(jié)構(gòu)混合在一起,所以如何嵌套也就非常的講究。例如,設計一個循環(huán)結(jié)構(gòu),結(jié)構(gòu)內(nèi)的循環(huán)語句只有在特定的條件下才被執(zhí)行,
Javascriptvar a = true; for (var i = 0; i < 10; i++) { if (a) {} //條件判斷 };
在這個循環(huán)里面,if語句會被反復的運行,如果這個if語句是一個固定的條件檢測表達式,如果if的條件不會受到循環(huán)結(jié)構(gòu)的影響,那么用下面這種結(jié)構(gòu)設計會更加復合:
Javascriptif (a) { for (var i = 0; i < 10; i++) { }; }
但是if條件表達式受循環(huán)結(jié)構(gòu)的制約,那就不能使用這種結(jié)構(gòu)嵌套了。
避免不必要的重復操作
在循環(huán)里面經(jīng)常會存在一些不必要的損耗。下面一個例子:
Javascriptfor (var i = 0; i < 10; i++) { var a= [1,2,3,4,5,6,7,8,9,10]; alert(a[i]); };
在這個循環(huán)里面,每循環(huán)一次就會在定義一個新的數(shù)組,很明顯這是一個重復的操作,把數(shù)組放到循環(huán)體外面會更加的高效:
Javascriptvar a= [1,2,3,4,5,6,7,8,9,10]; for (var i = 0; i < 10; i++) { alert(a[i]); };
妥善定義循環(huán)變量
對于for循環(huán)來說,它主要利用循環(huán)變量來控制整個結(jié)構(gòu)的運行。當循環(huán)變量僅用于結(jié)構(gòu)內(nèi)部的時候,不妨在for語句外面定義循環(huán)的變量,這樣也可以優(yōu)化循環(huán)結(jié)構(gòu)。
最后,如果文章有什么錯誤和疑問的地方,請指出。與sf各位共勉!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/91499.html
摘要:設計模式是以面向?qū)ο缶幊虨榛A的,的面向?qū)ο缶幊毯蛡鹘y(tǒng)的的面向?qū)ο缶幊逃行┎顒e,這讓我一開始接觸的時候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設計模式必須要先搞懂面向?qū)ο缶幊?,否則只會讓你自己更痛苦。 JavaScript 中的構(gòu)造函數(shù) 學習總結(jié)。知識只有分享才有存在的意義。 是時候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...
摘要:前端基礎進階正是圍繞這條線索慢慢展開,而事件循環(huán)機制,則是這條線索的最關鍵的知識點。特別是中正式加入了對象之后,對于新標準中事件循環(huán)機制的理解就變得更加重要。之后全局上下文進入函數(shù)調(diào)用棧。 showImg(https://segmentfault.com/img/remote/1460000008811705); JavaScript的學習零散而龐雜,因此很多時候我們學到了一些東西,但...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。寫一個符合規(guī)范并可配合使用的寫一個符合規(guī)范并可配合使用的理解的工作原理采用回調(diào)函數(shù)來處理異步編程。 JavaScript怎么使用循環(huán)代替(異步)遞歸 問題描述 在開發(fā)過程中,遇到一個需求:在系統(tǒng)初始化時通過http獲取一個第三方服務器端的列表,第三方服務器提供了一個接口,可通過...
摘要:我對知乎前端相關問題的十問十答張鑫旭張鑫旭大神對知乎上經(jīng)典的個前端問題的回答。作者對如何避免常見的錯誤,難以發(fā)現(xiàn)的問題,以及性能問題和不好的實踐給出了相應的建議。但并不是本身有問題,被標準定義的是極好的。 這一次,徹底弄懂 JavaScript 執(zhí)行機制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機制,如果讀完本文還不懂,可以揍我。 不論你是javascript新手還是老...
摘要:記筆記很有必要相信我,大多數(shù)人的記憶力是不可靠的。解決方式遍歷的順序不確定因為對象不是有序的。出租過程中趕走了某些房客。具體來說就是說存在某個空間沒有元素的數(shù)組便是稀疏數(shù)組怎么處理將會確認這個位置有沒有元素存在。同檢查元素是否存在 記筆記很有必要——相信我,大多數(shù)人的記憶力是不可靠的。 ——《與時間做朋友》李笑來 數(shù)組 值的有序集合 弱類型 數(shù)組中的元素可以是各種類型的 ...
閱讀 989·2021-11-25 09:43
閱讀 1356·2021-11-17 09:33
閱讀 3080·2019-08-30 15:44
閱讀 3380·2019-08-29 17:16
閱讀 537·2019-08-28 18:20
閱讀 1725·2019-08-26 13:54
閱讀 615·2019-08-26 12:14
閱讀 2234·2019-08-26 12:14