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