您好,登錄后才能下訂單哦!
這篇文章主要介紹javascript中3種for循環(huán)風(fēng)格的使用示例,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
在學(xué)習(xí)任何開(kāi)發(fā)語(yǔ)言時(shí)候,for循環(huán)是必不可少的一種語(yǔ)法,可能所有開(kāi)發(fā)人員都會(huì)使用它。它非常經(jīng)典,以至于每個(gè)開(kāi)發(fā)語(yǔ)言都至少包括一種關(guān)于循環(huán)的語(yǔ)法版本。不過(guò),在JavaScript種包含了三種不同的循環(huán)語(yǔ)法(如果再講究一點(diǎn),也可以算作是四種)。
它們的使用方式并不完全相同,舉例如下:
l 經(jīng)典的For循環(huán)語(yǔ)法
l For….of 及 For…in
l 炫技一點(diǎn)的版本:.forEach
接下來(lái),我想介紹下這三種語(yǔ)法使用時(shí)有什么異同,以及在什么時(shí)間怎樣使用它們才能收獲最棒的結(jié)果。好的,讓我們開(kāi)始吧。
這個(gè)語(yǔ)法我們應(yīng)該都已經(jīng)非常清楚了,在for循環(huán)中,你可以在其中定義內(nèi)部計(jì)數(shù)器,設(shè)置相應(yīng)中斷條件和靈活的步進(jìn)策略(通??梢允沁f增也可以是遞減)。
語(yǔ)法為:
for([計(jì)數(shù)器定義];[中斷條件];[步進(jìn)策略]){ //... TODO }
我敢肯定即便不用我的介紹,之前你也一定寫過(guò)類似的語(yǔ)句,例如:
for(let counter = 0; counter < 10; counter++) { console.log(counter) }
讓我們?cè)贑hrome里運(yùn)行一下,得到的結(jié)果也符合預(yù)期,但for循環(huán)就僅僅如此了嗎?
你可以認(rèn)為for循環(huán)為三個(gè)表達(dá)式
for( [在循環(huán)開(kāi)始時(shí)只執(zhí)行一次的表達(dá)式]; [其中每一個(gè)邏輯判斷都需吻合的表達(dá)式]; [循環(huán)每一步都被執(zhí)行的表達(dá)式] )
這樣表述的意義在于,你可以使用多個(gè)計(jì)數(shù)器執(zhí)行for循環(huán),或在不影響計(jì)數(shù)器的情況下在步進(jìn)表達(dá)式中執(zhí)行每次需要執(zhí)行的代碼,舉個(gè)例子:
for(let a = 0, b = 0; a < 10 && b < 100; a++, b+=10) { console.log(a, b) }
我們可以再進(jìn)一步,讓其變的更符合實(shí)際應(yīng)用場(chǎng)景:
for(let a = 0, b = 0; a < 10 && b < 100; console.log("你的計(jì)數(shù)器現(xiàn)在是:", ++a, b+=2)){}
另外,你甚至可以把中間表達(dá)式替換為函數(shù)調(diào)用,只要你記住,該函數(shù)的返回值需要是一個(gè)布爾型或可以被轉(zhuǎn)成布爾值的一個(gè)值即可,例如:
function isItDone(a) { console.log("函數(shù)被調(diào)用!") return a < 10 } for(let a = 0; isItDone(a); a++) { console.log(a) }
那么,在經(jīng)典的for循環(huán)中如何處理異步代碼呢?如何保證不掉進(jìn)異步陷阱里呢?
我為大家介紹一位新朋友:async / await,這將讓我們?cè)谔幚懋惒酱a時(shí)變得更容易、可控,例如:
const fs = require("fs") async function read(fname) { return new Promise( (resolve, reject) => { fs.readFile(fname, (err, content) => { if(err) return reject(err) resolve(content.toString()) }) }) } (async () => { let files = ['file1.json', 'file2.json'] for(let i = 0; i < files.length; i++) { let fcontent = await read(files[i]) console.log(fcontent) console.log("-------") } })()
他們看起來(lái)非常相似,但它們并不是相同類型的循環(huán)。
讓我們盡量簡(jiǎn)要的解釋它們:
For…in 循環(huán)遍歷對(duì)象的可枚舉屬性,也就是說(shuō)當(dāng)你的自定義對(duì)象被用作哈希表或字典時(shí),使用For…in 遍歷他們時(shí)將變得非常簡(jiǎn)單。
但請(qǐng)注意,遍歷順序是按元素順序執(zhí)行執(zhí)行的,因此請(qǐng)不要依賴循環(huán)順序。
let myMap { uno: 1, dos: 2, tres: 3 } for(let key in myMap) { console.log(key, "=", myMap[key]); }
看起來(lái)是很簡(jiǎn)單的,但請(qǐng)記住,F(xiàn)or…in只能遍歷一個(gè)實(shí)體對(duì)象,如果便利一個(gè)非實(shí)體,例如遍歷一個(gè)string,那么將會(huì)發(fā)生如下情況:
for(let k in "Hello World!") { console.log(k) }
從結(jié)果可以看到,并沒(méi)有遍歷出每一個(gè)字母,而是遍歷到了每個(gè)屬性,正如您看到的,遍歷出的數(shù)字并非是沒(méi)有用的,因?yàn)?quot;Hello World!"[1] 同樣是可以返回相應(yīng)的字母的。
相反,如果你想遍歷每個(gè)字符,則需要使用其他變體:For…of
for(let char of "Hello World!") { console.log(char) }
這種循環(huán)方式看起來(lái)對(duì)string類型更有效,相同的用例,因?yàn)槭褂昧诉@種語(yǔ)法,就能夠返回元素中相應(yīng)的值了。所以我們通過(guò)上述用例可知,F(xiàn)or…of遍歷的內(nèi)容是對(duì)象的值。
通過(guò)上述的示例我們可知,他們相互一個(gè)遍歷屬性,一個(gè)遍歷值,那么有沒(méi)有什么方法可以既獲得屬性又獲得值呢,答案是有的,使用entries方法,就可以同時(shí)獲得屬性和值,如下所示:
let myArr = ["hello", "world"] for([idx, value] of myArr.entries()) { console.log(idx, '=', value) }
最后,在處理異步代碼時(shí)是怎樣的呢?答案當(dāng)然是和for循環(huán)相同了。
const fs = require("fs") async function read(fname) { return new Promise( (resolve, reject) => { fs.readFile(fname, (err, content) => { if(err) return reject(err) resolve(content.toString()) }) }) } (async () => { let files = ['file2.json', 'file2.json'] for(fname of files) { let fcontent = await read(fname) console.log(fcontent) console.log("-------") } for(idx in files) { let fcontent = await read(files[idx]) console.log(fcontent) console.log("-------") } })()
最后我們?cè)偈褂煤?jiǎn)短的方式來(lái)總結(jié)下For…in和For…of的區(qū)別
For…in——遍歷屬性
For…of——遍歷值
這可能是我最喜歡的一個(gè),這僅僅是因?yàn)槲曳浅O矚g聲明式語(yǔ)法或通過(guò)命令式編寫代碼的聲明性方式。
而且,盡管上面的循環(huán)語(yǔ)法也很好用,并且都有很好的用例,但當(dāng)我們需要關(guān)注數(shù)據(jù)本身時(shí),forEach很好用。
不管怎樣,先撇開(kāi)哲學(xué)上的爭(zhēng)論不談,.foreach方法是for循環(huán)的另一個(gè)版本,但是這個(gè)方法是數(shù)組對(duì)象的一部分,它的目的是接收一個(gè)函數(shù)和一個(gè)額外的可選參數(shù),以便在執(zhí)行函數(shù)時(shí)重新定義該函數(shù)的上下文。
對(duì)于數(shù)組中的每個(gè)元素,我們的函數(shù)都將被執(zhí)行,并且它將收到三個(gè)參數(shù)(是的,就是三個(gè),而不是一個(gè),因?yàn)槟呀?jīng)習(xí)慣了使用它)。它們分別是:
正在處理的當(dāng)前元素。
元素的索引,這已經(jīng)簡(jiǎn)化了我們?cè)噲D用for…of循環(huán)實(shí)現(xiàn)的任務(wù)
正在處理的實(shí)際數(shù)組。以防萬(wàn)一你需要做點(diǎn)什么。
那么,讓我們看一個(gè)簡(jiǎn)單的示例:
a = ["hello", "world"] a.forEach ( (elem, idx, arr) => { console.log(elem, "at: ", idx, "inside: ", arr) })
更快更簡(jiǎn)單,不是嗎?
但是你可以看到我們?nèi)绾卧诤瘮?shù)中很容易地使用所有屬性。下面是一個(gè)您希望在foreach方法上使用第二個(gè)可選參數(shù)的示例:
class Person { constructor(name) { this.name = name } } function greet(person) { console.log(this.greeting.replace("$", person.name)) } let english = { greeting: "Hello there, $" } let spanish = { greeting: "Hola $, ?cómo estás?" } let people = [new Person("Fernando"), new Person("Federico"), new Person("Felipe")] people.forEach( greet, english) people.forEach( greet, spanish)
通過(guò)重寫被調(diào)用函數(shù)greet的上下文,我可以在不影響其代碼的情況下更改其行為。
最后,顯示此方法也可以與異步代碼一起使用,下面是示例:
const fs = require("fs") async function read(fname) { return new Promise( (resolve, reject) => { fs.readFile(fname, (err, content) => { if(err) return reject(err) resolve(content.toString()) }) }) } let files = ['file1.json', 'file2.json'] files.forEach( async fname => { let fcontent = await read(fname) console.log(fcontent) console.log("-------") })
以上是“javascript中3種for循環(huán)風(fēng)格的使用示例”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。