循環(huán)吧代碼

2018-05-15 17:26 更新
前提條件: 基本的電腦知識,對HTML與CSS有基本的了解,及已閱讀: JavaScript first steps(JS的入門).
目標(biāo): 學(xué)習(xí)如何在JS里面使用循環(huán)語句.

來一起循環(huán)

循環(huán),循環(huán),循環(huán). 就與這些:popular breakfast cereals, roller coasters and musical production一樣,類似存在于編程中.編程中的循環(huán)也是一直重復(fù)著去做一件事 - 此處循環(huán)便是編程中的術(shù)語.

讓我們來想一下下圖,這位農(nóng)夫考慮為他的家庭做一周的食物計劃,他或許就需要執(zhí)行一段循環(huán):


一段循環(huán)通常需要一個活多個條件:

  • 一個開始條件, which is initialized with a certain value — this is the starting point of the loop ("Start: I have no food", above).
  • 一個結(jié)束條件, which is the criteria under which the loop stops — usually the counter reaching a certain value. This is illustrated by "Have I got enough food?", above. Let's say he needs 10 portions of food to feed his family.
  • 一個容器, which generally increments the counter by a small amount on each successive loop, until it reaches the exit condition. We haven't explicitly illustrated this above, but we could think about the farmer being able to collect say 2 portions of food per hour. After each hour, the amount of food he has collected is incremented by two, and he checks whether he has enough food. If he has reached 10 portions (the exit condition), he can stop collecting and go home.

偽代碼中,這將類似于以下內(nèi)容:

loop(food = 0; foodNeeded = 10) {
  if (food = foodNeeded) {
    exit loop;
    // We have enough food; let's go home
  } else {
    food += 2; // Spend an hour collecting 2 more food
    // loop will then run again
  }
}

因此,所需的食物量設(shè)置為10,并且農(nóng)民目前具有的量設(shè)置為0.在循環(huán)的每次迭代中,我們檢查農(nóng)民的食物量是否等于他需要的量。 如果是這樣,我們可以退出循環(huán)。 如果不是,農(nóng)民花了一個小時收集兩份食物,環(huán)路再次運行。

何必?

在這一點上,你可能會理解循環(huán)的高層概念,但你可能認為"OK,好,但是這如何幫助我編寫更好的JavaScript代碼? 正如我們之前所說,循環(huán)是一次又一次地做同樣的事情,這對于快速完成重復(fù)任務(wù)非常有用。

通常,代碼將在循環(huán)的每個連續(xù)迭代中略有不同,這意味著您可以完成類似但略有不同的任務(wù)的整個加載 - 如果您有很多不同的計算要做, 做每一個不同的,不一樣的一遍又一遍!

讓我們看一個例子來完美地說明為什么循環(huán)是這樣好的東西。 假設(shè)我們要在 < canvas> 元素上繪制100個隨機圓圈(按 更新按鈕一次運行該示例以查看不同的隨機集):

你現(xiàn)在不必理解所有的代碼(你可以在GitHub上看到完整的源代碼,看到在單獨的窗口中運行的示例),但讓我們看看實際畫出100個圓圈的代碼部分:

for (var i = 0; i < 100; i++) {
  ctx.beginPath();
  ctx.fillStyle = 'rgba(255,0,0,0.5)';
  ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);
  ctx.fill();
}

你應(yīng)該得到基本的想法 - 我們使用一個循環(huán)來運行這個代碼的100次迭代,每個迭代在頁面上的隨機位置繪制一個圓。 無論我們繪制100個圓,1000或10,000,所需的代碼量都是相同的。 只有一個數(shù)字必須更改。

如果我們沒有在這里使用循環(huán),我們必須為每個要繪制的圓重復(fù)以下代碼:

ctx.beginPath();
ctx.fillStyle = 'rgba(255,0,0,0.5)';
ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);
ctx.fill();

這將非常無聊,很難很快維持。 循環(huán)真的是最好的。

循環(huán)的標(biāo)準(zhǔn)

讓我們開始探索一些特定的循環(huán)結(jié)構(gòu)。 您最常使用的第一個是 a> loop - 這有以下語法:

for (initializer; exit-condition; final-expression) {
  // code to run
}

這里我們有:

  1. The keyword for, followed by some parentheses.
  2. Inside the parentheses we have three items, separated by semi-colons:
    1. An initializer — this is usually a variable set to a number, which is incremented to count the number of times the loop has run. It is also sometimes referred to as a counter variable.
    2. An exit-condition — as mentioned before, this defines when the loop should stop looping. This is generally an expression featuring a comparison operator, a test to see if the exit condition has been met.
    3. A final-expression — this is always evaluated (or run) each time the loop has gone through a full iteration. It usually serves to increment (or in some cases decrement) the counter variable, to bring it closer to the exit condition value.
  3. Some curly braces that contain a block of code — this code will be run each time the loop iterates.

讓我們看一個真實的例子,所以我們可以想象這些做得更清楚。

var cats = ['Bill', 'Jeff', 'Pete', 'Biggles', 'Jasmin'];
var info = 'My cats are called ';
var para = document.querySelector('p');

for (var i = 0; i < cats.length; i++) {
  info += cats[i] + ', ';
}

para.textContent = info;

這給了我們以下輸出:

這顯示了一個循環(huán),用于遍歷數(shù)組中的項目,并對其中的每一個執(zhí)行一些操作 - 這是JavaScript中的一種常見模式。 這里:

  1. The iterator, i, starts at 0 (var i = 0).
  2. It has been told to run until it is no longer smaller than the length of the cats array. This is important — the exit condition shows the condition under which the loop will still run. So in this case, while i < cats.length is still true, the loop will still run.
  3. Inside the loop, we concatenate the current loop item (cats[i] is cats[whatever i is at the time]) along with a comma and a space, onto the end of the info variable. So:
    1. During the first run, i = 0, so cats[0] + ', ' will be concatenated onto info ("Bill, ").
    2. During the second run, i = 1, so cats[1] + ', ' will be concatenated onto info ("Jeff, ")
    3. And so on. After each time the loop has run, 1 will be added to i (i++), then the process will start again.
  4. When i becomes equal to cats.length, the loop will stop, and the browser will move on to the next bit of code below the loop.

注意:我們已設(shè)置退出條件 i< cats.length 而不是 i ,因為計算機從0開始計數(shù),而不是1 - 我們在 / code>,并向上到 i = 4 (最后一個數(shù)組項的索引)。 cats.length 返回5,因為數(shù)組中有5個項目,但我們不想到 i = 5 ,因為會返回 未定義(沒有索引為5的數(shù)組項)。 因此,我們想要比 cats.length ( i )少1,而不是 cats.length code> i )。

注意:退出條件的常見錯誤是使用"等于"而不是說"小于或等于"。 如果我們想要運行循環(huán)直到i = 5,退出條件將需要是i 等于5在第一次循環(huán)迭代,所以它會立即停止。

我們剩下的一個小問題是最后的輸出句子不是很好:

我的貓叫Bill,Jeff,Pete,Biggles,Jasmin,

理想情況下,我們想改變最后循環(huán)迭代的連接,以便我們在句子末尾沒有逗號。 嗯,沒有問題 - 我們可以很高興地在我們的for循環(huán)中插入一個條件來處理這個特殊情況:

for (var i = 0; i < cats.length; i++) {
  if (i === cats.length - 1) {
    info += 'and ' + cats[i] + '.';
  } else {
    info += cats[i] + ', ';
  }
}

重要:使用for - 與所有循環(huán)一樣,您必須確保初始化程序被迭代,以便最終達到退出條件。 如果沒有,循環(huán)將永遠繼續(xù),瀏覽器將強制它停止,否則會崩潰。 這稱為無限循環(huán)。

退出循環(huán)中斷

如果要在所有迭代完成之前退出循環(huán),可以使用 > break 語句。 當(dāng)我們查看切換語句時,在switch語句中遇到一個情況時,我們在前一篇文章中已經(jīng)滿足了這一點 匹配輸入表達式,break語句立即退出switch語句并移動到它之后的代碼。

它與循環(huán)一樣 - break 語句將立即退出循環(huán),并使瀏覽器移動到其后的任何代碼。

說我們想要通過一系列聯(lián)系人和電話號碼進行搜索,并只返回我們想要找到的號碼? 首先是一些簡單的HTML - < input> 允許我們輸入名稱 以搜索要提交搜索的 < button> 元素, a href ="/ zh-CN / docs / Web / HTML / Element / p"> < p> 元素,

<label for="search">Search by contact name: </label>
<input id="search" type="text">
<button>Search</button>

<p></p>

現(xiàn)在對JavaScript:

var contacts = ['Chris:2232322', 'Sarah:3453456', 'Bill:7654322', 'Mary:9998769', 'Dianne:9384975'];
var para = document.querySelector('p');
var input = document.querySelector('input');
var btn = document.querySelector('button');

btn.addEventListener('click', function() {
  var searchName = input.value;
  input.value = '';
  input.focus();
  for (var i = 0; i < contacts.length; i++) {
    var splitContact = contacts[i].split(':');
    if (splitContact[0] === searchName) {
      para.textContent = splitContact[0] + '\'s number is ' + splitContact[1] + '.';
      break;
    } else {
      para.textContent = 'Contact not found.';
    }
  }
});

  1. First of all we have some variable definitions — we have an array of contact information, with each item being a string containing a name and phone number separated by a colon.
  2. Next, we attach an event listener to the button (btn), so that when it is pressed, some code is run to perform the search and return the results.
  3. We store the value entered into the text input in a variable called searchName, before then emptying the text input and focusing it again, ready for the next search.
  4. Now onto the interesting part, the for loop:
    1. We start the counter at 0, run the loop until the counter is no longer less than contacts.length, and increment i by 1 after each iteration of the loop.
    2. Inside the loop we first split the current contact (contacts[i]) at the colon character, and store the resulting two values in an array called splitContact.
    3. We then use a conditional statement to test whether splitContact[0] (the contact's name) is equal to the inputted searchName. If it is, we enter a string into the paragraph to report what the contact's number is, and use break to end the loop.
  5. If the contact name does not match the entered search, the paragraph text is set to "Contact not found.", and the loop continues iterating.

注意:您可以查看完整的 GitHub上的源代碼和查看 它也運行生活。

使用continue跳過迭代

繼續(xù)語句的工作方式與 break / code>,但是不是完全打破循環(huán),而是跳過循環(huán)的下一次迭代。 讓我們看看另一個例子,它接受一個數(shù)字作為輸入,并且只返回整數(shù)的正方形數(shù)字(整數(shù))。

HTML基本上與上一個示例相同 - 一個簡單的文本輸入和一個用于輸出的段落。 JavaScript大部分是相同的,雖然循環(huán)本身有點不同:

var num = input.value;

for (var i = 1; i <= num; i++) {
  var sqRoot = Math.sqrt(i);
  if (Math.floor(sqRoot) !== sqRoot) {
    continue;
  }

  para.textContent += i + ' ';
}

這里是輸出:

  1. In this case, the input should be a number (num). The for loop is given a counter starting at 1 (as we are not interested in 0 in this case), an exit condition that says the loop will stop when the counter becomes bigger than the input num, and an iterator that adds 1 to the counter each time.
  2. Inside the loop, we find the square root of each number using Math.sqrt(i), then check whether the square root is an integer by testing whether it is the same as itself when it has been rounded down to the nearest integer (this is what Math.floor() does to the number it is passed).
  3. If the square root and the rounded down square root do not equal one another (!==), it means that the square root is not an integer, so we are not interested in it. In such a case, we use the continue statement to skip on to the next loop iteration without recording the number anywhere.
  4. If the square root IS an integer, we skip past the if block entirely so the continue statement is not executed; instead, we concatenate the current i value plus a space on to the end of the paragraph content.

而同時

for 不是JavaScript中唯一可用的循環(huán)類型。 實際上有很多其他的,雖然你現(xiàn)在不需要了解所有這些,但值得看看一些其他人的結(jié)構(gòu),以便你可以以一種稍微不同的方式在工作中識別相同的功能。

首先,讓我們看看 while 循環(huán)。 這個循環(huán)的語法如下:

initializer
while (exit-condition) {
  // code to run

  final-expression
}

除了在循環(huán)之前設(shè)置初始化器變量,并且final-expression包含在運行代碼之后的循環(huán)內(nèi),而不是括號內(nèi)包含這兩個項目之外,它的工作方式與for循環(huán)非常相似。 退出條件包含在括號內(nèi),其前面有 while 關(guān)鍵字,而不是的。

同樣的三個項目仍然存在,它們?nèi)匀灰耘c它們在for循環(huán)中相同的順序定義 - 這是有意義的,因為您仍然必須定義初始化器,然后才能檢查它是否已達到退出條件 ; 最終條件然后在循環(huán)中的代碼已經(jīng)運行(迭代已經(jīng)完成)之后運行,這將僅在仍然未達到退出條件時發(fā)生。

讓我們再看看我們的cats列表示例,但重寫為使用while循環(huán):

var i = 0;

while (i < cats.length) {
  if (i === cats.length - 1) {
    info += 'and ' + cats[i] + '.';
  } else {
    info += cats[i] + ', ';
  }

  i++;
}

注意:此效果仍然與預(yù)期相同 - 請查看 while.html"class ="external">在GitHub上運行(也可以查看 /loops/while.html"class ="external">完整的源代碼)。

do ... while 循環(huán)非常相似 ,但提供了while結(jié)構(gòu)的變化:

initializer
do {
  // code to run

  final-expression
} while (exit-condition)

在這種情況下,初始化器再次來到循環(huán)開始之前。 do 關(guān)鍵字直接位于包含要運行的代碼和final-expression的花括號之前。

這里的區(qū)別是退出條件在所有其他之后,包裹在括號中,并且在 while 關(guān)鍵字之前。 在 do ... while 循環(huán)中,花括號中的代碼總是運行一次,然后再進行檢查,看看是否應(yīng)該再次執(zhí)行(在while和for中,檢查首先, 所以代碼可能永遠不會被執(zhí)行)。

讓我們重寫我們的cat列表示例以使用 do ... while loop:

var i = 0;

do {
  if (i === cats.length - 1) {
    info += 'and ' + cats[i] + '.';
  } else {
    info += cats[i] + ', ';
  }

  i++;
} while (i < cats.length);

重要:使用while和do ... while - 與所有循環(huán)一樣,您必須確保初始化器被迭代,以便最終達到退出條件。 如果沒有,循環(huán)將永遠繼續(xù),瀏覽器將強制它停止,否則會崩潰。 這稱為無限循環(huán)。

主動學(xué)習(xí):啟動倒計時!

在本練習(xí)中,我們希望您打印出一個簡單的啟動倒計時到輸出框,從10下降到Blast off。 具體來說,我們希望您:

  • Loop from 10 down to 0. We've provided you with an initializer — var i = 10;.
  • For each iteration, create a new paragraph and append it to the output <div>, which we've selected using var output = document.querySelector('.output');. In comments, we've provided you with three code lines that need to be used somewhere inside the loop:
    • var para = document.createElement('p'); — creates a new paragraph.
    • output.appendChild(para); — appends the paragraph to the output <div>.
    • para.textContent = — makes the text inside the paragraph equal to whatever you put on the right hand side, after the equals sign.
  • Different iteration numbers require different text to be put in the paragraph for that iteration (you'll need a conditional statement and multiple para.textContent = lines):
    • If the number is 10, print "Countdown 10" to the paragraph.
    • If the number is 0, print "Blast off!" to the paragraph.
    • For any other number, print just the number to the paragraph.
  • Remember to include an iterator! However, in this example we are counting down after each iteration, not up, so you don't want i++ — how do you iterate downwards?

如果出錯,您可以隨時使用"重置"按鈕重置示例。 如果你真的卡住,按"顯示解決方案"看到一個解決方案。

主動學(xué)習(xí):填寫訪客名單

在本練習(xí)中,我們希望您獲取存儲在數(shù)組中的名稱列表,并將其放入guest虛擬機列表中。 但它不是那么容易 - 我們不想讓菲爾和洛拉因為他們貪婪和粗魯,總是吃所有的食物! 我們有兩個名單,一個是客人承認,一個是客人拒絕。

具體來說,我們希望您:

  • Write a loop that will iterate from 0 to the length of the people array. You'll need to start with an initializer of? var i = 0;, but what exit condition do you need?
  • During each loop iteration, check if the current array item is equal to "Phil" or "Lola" using a conditional statement:
    • If it is, concatenate the array item to the end of the refused paragraph's textContent, followed by a comma and a space.
    • If it isn't, concatenate the array item to the end of the admitted paragraph's textContent, followed by a comma and a space.

我們已經(jīng)為您提供:

  • var i = 0; — Your initializer.
  • refused.textContent += — the beginnings of a line that will concatenate something on to the end of refused.textContent.
  • admitted.textContent += — the beginnings of a line that will concatenate something on to the end of admitted.textContent.

額外的獎金問題 - 成功完成上述任務(wù)后,您將留下兩個名稱列表,用逗號分隔,但它們將不整潔 - 每個結(jié)尾處都有一個逗號。 你能找出如何編寫在每種情況下切分最后一個逗號的行,并添加一個完整的句點到底? 有關(guān)幫助,請查看有用的字符串方法文章。

如果出錯,您可以隨時使用"重置"按鈕重置示例。 如果你真的卡住,按"顯示解決方案"看到一個解決方案。

你應(yīng)該使用哪個循環(huán)類型?

對于基本使用, , while do ... while 循環(huán)在很大程度上是可互換的。 他們都可以用來解決相同的問題,你使用哪一個很大程度上取決于你的個人喜好 - 哪一個你發(fā)現(xiàn)最容易記住或最直觀。 讓我們再看看一下。

第一個 for :

for (initializer; exit-condition; final-expression) {
  // code to run
}

while :

initializer
while (exit-condition) {
  // code to run

  final-expression
}

最后 do ... while :

initializer
do {
  // code to run

  final-expression
} while (exit-condition)

我們推薦 for ,至少從開始,因為它可能是最容易記住一切 - 初始化,退出條件和最終表達式都必須整齊地放在括號中,所以它 很容易看到他們在哪里,并檢查,你不是錯過他們。

注意:還有其他循環(huán)類型/功能,這在高級/特殊情況下有用,超出了本文的范圍。 如果您想進一步了解循環(huán)學(xué)習(xí),請參閱我們的高級循環(huán)和迭代指南 a>。

結(jié)論

本文向您展示了基本概念,以及在JavaScript中循環(huán)代碼時可用的不同選項。 你現(xiàn)在應(yīng)該明確為什么循環(huán)是一個處理重復(fù)代碼的好機制,并且在你自己的例子中使用它們。

如果您有任何不明白的地方,請隨時閱讀本文,或與我們聯(lián)系以尋求幫助。

也可以看看

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號