摘要:所以結(jié)果的不同就是后者能將循環(huán)內(nèi)容至少執(zhí)行一次。當此語句省略時,表示不進行條件判斷,循環(huán)將一直執(zhí)行,只有在循環(huán)中使用來跳出循環(huán)。支持對數(shù)組和類數(shù)組對象進行循環(huán),不支持普通對象的循環(huán)。支持對字符串進行循環(huán)遍歷。
JavaScript中直接提供的循環(huán),主要有以下幾種
while 循環(huán)和其他語言一樣,JavaScript中的while循環(huán)有兩種形式:
while (condition) { // 循環(huán)內(nèi)容 } do { // 循環(huán)內(nèi)容 } while (condition)
其中兩種形式的不同在于,對condition判斷的位置不同,前者先判斷,再執(zhí)行循環(huán)體;而后者先執(zhí)行循環(huán)體一次,再進行條件判斷。所以結(jié)果的不同就是后者能將循環(huán)內(nèi)容至少執(zhí)行一次。
for 循環(huán)for循環(huán)的語法:
for (init; condition; step) { // 循環(huán)體代碼塊 }
init 語句 中的內(nèi)容,會在循環(huán)代碼開始前執(zhí)行一次,通常用來聲明一些變量。
condition 語句 會在每次循環(huán)開始時,進行判斷。如果第一次就不滿足,則不會進入循環(huán)。
step 語句 會在每次循環(huán)結(jié)束時執(zhí)行,通常是遞增或遞減condition中的某個變量。
var arr = [0, 10, 20, 30]; for (var j = 0; j < arr.length; j++) { console.log(arr[j]); } // 如果在循環(huán)體中不會改變數(shù)組的長度,用一個變量存儲數(shù)組長度是個更高效的選擇 for (var i = 0, l = arr.length; i < l; i++) { console.log(arr[i]); } var k = 0, length = arr.length; for (; k < length; k++) { console.log(arr[k]); }
for循環(huán)中的init語句,通常用來聲明初始變量,其可以有多個,用,分隔即可。而且由于此語句是在循環(huán)開始前執(zhí)行,且只用執(zhí)行一次,所以如果在外部已經(jīng)聲明過要用的變量了,for循環(huán)中的這個語句可以直接省略,如上例中的第三個for循環(huán)所示。
for循環(huán)的條件語句是在每次循環(huán)體開始前進行判斷,如果為true,則執(zhí)行循環(huán)體內(nèi)容,否則結(jié)束循環(huán)。當此語句省略時,表示不進行條件判斷,循環(huán)將一直執(zhí)行,只有在循環(huán)中使用break來跳出循環(huán)。
for循環(huán)的step語句,最常見的就是使用++或者-- 運算符的表達式,不過也可以使用其他任意值的,而且也可以省略,換到循環(huán)體中進行改變賦值。
for-in 循環(huán)for-in循環(huán)是JavaScript中專門提供用來遍歷對象屬性的。
var zs = { name: "zhang san", gender: "male", age: 26 }; for (var key in zs) { console.log("%s : %s", key, zs[key]); } // name : zhang san // gender : male // age : 26
不過需要注意一點問題,請看如下示例:
function Person(name, gender) { this.name = name; this.gender = gender; } Person.prototype.sayHello = function() { console.log("Hello,I am", this.name, ". I"m a", this.gender); }; var zs = new Person("zhang san", "male"); for (var key in zs) { console.log("%s : %s",key, zs[key]); } // name : zhang san // gender : male // sayHello : function () { // console.log("Hello,I am", this.name, ". I"m a", this.gender); // }
這次循環(huán)遍歷中,它還輸出了zs原型鏈上的屬性sayHello。這反應(yīng)出一個問題,for - in 循環(huán)會遍歷整個原型鏈,雖然可以使用hasOwnProperty方法進行過濾僅獲取自身屬性,但其訪問的仍是整個原型鏈,遍歷范圍較廣,所以其效率比較低,通常來說,其效率僅為普通for循環(huán)的1/7。
在JavaScript中,由于數(shù)組也是對象,所以此方法也可以用來遍歷數(shù)組。
var arr = [1, 2, 3, 4]; for (var i in arr) { console.log(typeof i); if (arr.hasOwnProperty(i)) console.log("arr[%s] : %d", i, arr[i]); else console.log("arr.%s : ", i, arr.[i]); } // string // arr[0] : 1 // string // arr[1] : 2 // string // arr[2] : 3 // string // arr[3] : 4 // string // arr.where : function ... // string // arr.groupBy : function ... // string // arr.has : function ...
這個輸出的結(jié)果或許不是你想象的樣子,然而他就是這樣。我們認為的索引,實際是對象的鍵名,所以其是String類型。對于數(shù)組來說,和對象一樣,在其原型上擴展的方法where、groupBy、has也都被輸出了。 或許會有疑問,數(shù)組不是有length屬性嗎,為什么沒有輸出呢?原因在于數(shù)組的length屬性是不可枚舉屬性,for - in循環(huán)不會訪問這些屬性。關(guān)于此的更多知識可參考MDN - 屬性的可枚舉性和所有權(quán)
Array 在 Javascript 中是一個對象, Array 的索引是屬性名。事實上, Javascript 中的 “array” 有些誤導(dǎo)性, Javascript 中的 Array 并不像大部分其他語言的數(shù)組。首先, Javascript 中的 Array 在內(nèi)存上并不連續(xù),其次, Array 的索引并不是指偏移量。實際上, Array 的索引也不是 Number 類型,而是 String 類型的。我們可以正確使用如 arr[0] 的寫法的原因是語言可以自動將 Number 類型的 0 轉(zhuǎn)換成 String 類型的 "0" 。所以,在 Javascript 中從來就沒有 Array 的索引,而只有類似 "0" 、 "1" 等等的屬性。
for - in 循環(huán)原本就是用來遍歷對象的,用其來遍歷數(shù)組并不合適,不過也有例外的情況,比如稀疏數(shù)組:
var arr = new Array(1000); arr[0] = 1; arr[99] = 3; arr[999] = 5; // for循環(huán) for (var i = 0, l = arr.length; i < l; i++) { console.log("arr[%s]", i, arr[i]); } console.log("i :" , i); // ... // arr[0] 1 // ... // arr[99] 3 // ... // arr[999] 5 // i : 1000 // for - in 循環(huán) var count = 0; for(var j in arr){ count ++ ; if(arr.hasOwnProperty(j)){ console.log("arr[%s]", j, arr[j]); } } console.log("count : ", count); // arr[0] 1 // arr[99] 3 // arr[999] 5 // i : 1000
直接使用普通的for循環(huán),循環(huán)次數(shù)為數(shù)組長度1000次,而使用for - in循環(huán),僅僅循環(huán)了3次。
上面看起來循環(huán)的效率是高了不少,但是在前面已經(jīng)說過了,for - in 的專職是對象的遍歷(類似的還有Object.keys()),因此上面的方案并非是一個完美的方案,更好的做法是用是數(shù)組本身的遍歷方法forEach(forEach為ES5中新增,需要IE9+)。
var arr = new Array(1000); arr[0] = 1; arr[99] = 3; arr[999] = 5; var count = 0; arr.forEach(function(value, index) { count++; console.log(typeof index); console.log(index, value); }); console.log("count", count); // number // 0 1 // number // 99 3 // number // 999 5 // count 3
這樣就高效地進行了循環(huán)遍歷,而且數(shù)組的索引index也被正確地識別為了number類型。
或許你會想到jQuery中提供的工具方法$.each()和$.map()或者實例jQuery對象的each和map方法,但是結(jié)果會讓你失望的,依舊會是循環(huán)1000次,以下是示例:
var count1 = 0; $.each(arr, function(index, value) { count1++; console.log(index, value); }); console.log("count1",count1); // count1 1000 var count2 = 0; $.map(arr,function(value,index){ count2++; console.log(index, value); }); console.log("count2",count2); // count2 1000
從上面對比來看Array.prototype.forEach方法似乎不錯,但其循環(huán)效率仍然不如普通的for循環(huán),不過優(yōu)勢在于在稀疏數(shù)組的處理。
不過forEach方法,嚴格來算并不算是循環(huán),原因在于,它并不能響應(yīng)循環(huán)應(yīng)有的break和continue語句。準確地講,它是一個遍歷函數(shù),對每個元素執(zhí)行指定的回調(diào)函數(shù)。
for-of循環(huán)ES6中又新增了for - of 循環(huán),它與for - in循環(huán)類似,但又有所不同。
for - of 支持對數(shù)組和類數(shù)組對象進行循環(huán),不支持普通對象的循環(huán)。
for - of 支持對字符串進行循環(huán)遍歷。
for - of 支持對Map 和 Set (ES6 中新增的類型)對象遍歷。
for - of 不支持普通對象的循環(huán)遍歷。
// 數(shù)組 var arr = [0, 1, 2, 3, 4, 5]; for (let index of arr) { if (index === 1) continue; if (index === 4) break; console.log(typeof index); console.log(index, arr[index]); } // number // 0 0 // number // 2 2 // number // 3 3
當索引為1時直接進行下一次循環(huán),而當索引為4時,直接退出循環(huán),因此輸出如上結(jié)果,也同樣正確識別索引為number類型。
// 類數(shù)組 // 類數(shù)組 var divs = document.querySelectorAll("div"); for (let i of divs) { console.log(i.classList); } // ["container", "md-doc", value: "container md-doc"] // ["doc-cata", value: "doc-cata"] // ["nicescroll-rails", "nicescroll-rails-vr", value: "nicescroll-rails nicescroll-rails-vr"] // ["nicescroll-cursors", value: "nicescroll-cursors"] // ["nicescroll-rails", "nicescroll-rails-hr", value: "nicescroll-rails nicescroll-rails-hr"] // ["nicescroll-cursors", value: "nicescroll-cursors"] for (let k in divs) { console.log(k, divs[k].classList); } // "0" ["container", "md-doc", value: "container md-doc"] // "1" ["doc-cata", value: "doc-cata"] // "2" ["nicescroll-rails", "nicescroll-rails-vr", value: "nicescroll-rails nicescroll-rails-vr"] // "3" ["nicescroll-cursors", value: "nicescroll-cursors"] // "4" ["nicescroll-rails", "nicescroll-rails-hr", value: "nicescroll-rails nicescroll-rails-hr"] // "5" ["nicescroll-cursors", value: "nicescroll-cursors"] // length undefined // item undefined // keys undefined // values undefined // entries undefined // forEach undefined
在for - of循環(huán)用于類數(shù)組對象的處理時,需要注意,of關(guān)鍵字前面的變量即為類數(shù)組對象中的鍵值,如上例所示,在for - of循環(huán)中i即代表著DOM nodelist 中的每個對象,而在for - in 循環(huán)中k代表的僅僅是對象的鍵名。
參考鏈接深入了解 JavaScript 中的 for 循環(huán)
JavaScript while循環(huán)
JavaScript for循環(huán)
MDN - 屬性的可枚舉性和所有權(quán)
原文發(fā)表在我的博客JavaScript 循環(huán),歡迎訪問!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/82174.html
摘要:主線程不斷重復(fù)上面的三步,此過程也就是常說的事件循環(huán)。所以主線程代碼執(zhí)行時間過長,會阻塞事件循環(huán)的執(zhí)行。參考資料這一次,徹底弄懂執(zhí)行機制任務(wù)隊列的順序機制事件循環(huán)搞懂異步事件輪詢與中的事件循環(huán) 1. 說明 讀過本文章后,您能知道: JavaScript代碼在瀏覽器中的執(zhí)行機制和事件循環(huán) 面試中經(jīng)常遇到的代碼輸出順序問題 首先通過一段代碼來驗證你是否了解代碼輸出順序,如果你不知道輸出...
摘要:有兩個主要因素有助于改善循環(huán)性能每次迭代完成的工作和迭代次數(shù)。第一個是標準的循環(huán),它與其他類語言的語法相同循環(huán)體這可能是最常用的循環(huán)結(jié)構(gòu)。解析循環(huán)由四部分組成初始化,預(yù)測試條件,循環(huán)體和后執(zhí)行。它將會不斷執(zhí)行,直到返回所有屬性為止。 翻譯:瘋狂的技術(shù)宅https://medium.freecodecamp.o... 本文首發(fā)微信公眾號:前端先鋒歡迎關(guān)注,每天都給你推送新鮮的前端技術(shù)...
摘要:此事件隊列的美妙之處在于它只是函數(shù)等待被調(diào)用和移動到調(diào)用棧的一個臨時存放區(qū)域。在事件循環(huán)不斷監(jiān)視調(diào)用棧是否為空現(xiàn)在確實是空的時候調(diào)用創(chuàng)建一個新的調(diào)用棧來執(zhí)行代碼。在執(zhí)行完之后進入了一個新的狀態(tài)這個狀態(tài)調(diào)用棧為空事件記錄表為空事件隊列也為空。 這篇文章是對個人認為講解 JavaScript 事件循環(huán)比較清楚的一篇英文文章的簡單翻譯,原文地址是http://altitudelabs.com...
摘要:總之,是用來循環(huán)帶有字符串的對象的方法。循環(huán)里引入了一種新的循環(huán)方法,它就是循環(huán),它既比傳統(tǒng)的循環(huán)簡潔,同時彌補了和循環(huán)的短板。 forEach 循環(huán) JavaScript誕生已經(jīng)有20多年了,我們一直使用的用來循環(huán)一個數(shù)組的方法是這樣的: for (var index = 0; index < myArray.length; index++) { console.log(myAr...
摘要:概述本篇主要介紹的運行機制單線程事件循環(huán)結(jié)論先在中利用運行至完成和非阻塞完成單線程下異步任務(wù)的處理就是先處理主模塊主線程上的同步任務(wù)再處理異步任務(wù)異步任務(wù)使用事件循環(huán)機制完成調(diào)度涉及的內(nèi)容有單線程事件循環(huán)同步執(zhí)行異步執(zhí)行定時器的事件循環(huán)開始 1.概述 本篇主要介紹JavaScript的運行機制:單線程事件循環(huán)(Event Loop). 結(jié)論先: 在JavaScript中, 利用運行至...
閱讀 2090·2021-10-09 09:41
閱讀 1670·2021-09-28 09:36
閱讀 1186·2021-09-26 09:55
閱讀 1365·2021-09-10 11:17
閱讀 1222·2021-09-02 09:56
閱讀 2826·2019-08-30 12:58
閱讀 2988·2019-08-29 13:03
閱讀 1917·2019-08-26 13:40