codecamp

循环吧代码

前提条件: 基本的电脑知识,对HTML与CSS有基本的了解,及已阅读: JavaScript first steps(JS的入门).
目标: 学习如何在JS里面使用循环语句.

来一起循环

循环,循环,循环. 就与这些:popular breakfast cereals, roller coasters and musical production一样,类似存在于编程中.编程中的循环也是一直重复着去做一件事 - 此处循环便是编程中的术语.

让我们来想一下下图,这位农夫考虑为他的家庭做一周的食物计划,他或许就需要执行一段循环:


一段循环通常需要一个活多个条件:

  • 一个开始条件, which is initialized with a certain value — this is the starting point of the loop ("Start: I have no food", above).
  • 一个结束条件, 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.

伪代码中,这将类似于以下内容:

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
  }
}

因此,所需的食物量设置为10,并且农民目前具有的量设置为0.在循环的每次迭代中,我们检查农民的食物量是否等于他需要的量。 如果是这样,我们可以退出循环。 如果不是,农民花了一个小时收集两份食物,环路再次运行。

何必?

在这一点上,你可能会理解循环的高层概念,但你可能认为"OK,好,但是这如何帮助我编写更好的JavaScript代码? 正如我们之前所说,循环是一次又一次地做同样的事情,这对于快速完成重复任务非常有用。

通常,代码将在循环的每个连续迭代中略有不同,这意味着您可以完成类似但略有不同的任务的整个加载 - 如果您有很多不同的计算要做, 做每一个不同的,不一样的一遍又一遍!

让我们看一个例子来完美地说明为什么循环是这样好的东西。 假设我们要在 < canvas> 元素上绘制100个随机圆圈(按 更新按钮一次运行该示例以查看不同的随机集):

你现在不必理解所有的代码(你可以在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();
}

你应该得到基本的想法 - 我们使用一个循环来运行这个代码的100次迭代,每个迭代在页面上的随机位置绘制一个圆。 无论我们绘制100个圆,1000或10,000,所需的代码量都是相同的。 只有一个数字必须更改。

如果我们没有在这里使用循环,我们必须为每个要绘制的圆重复以下代码:

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

这将非常无聊,很难很快维持。 循环真的是最好的。

循环的标准

让我们开始探索一些特定的循环结构。 您最常使用的第一个是 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;

这给了我们以下输出:

这显示了一个循环,用于遍历数组中的项目,并对其中的每一个执行一些操作 - 这是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.

注意:我们已设置退出条件 i< cats.length 而不是 i ,因为计算机从0开始计数,而不是1 - 我们在 / code>,并向上到 i = 4 (最后一个数组项的索引)。 cats.length 返回5,因为数组中有5个项目,但我们不想到 i = 5 ,因为会返回 未定义(没有索引为5的数组项)。 因此,我们想要比 cats.length ( i )少1,而不是 cats.length code> i )。

注意:退出条件的常见错误是使用"等于"而不是说"小于或等于"。 如果我们想要运行循环直到i = 5,退出条件将需要是i 等于5在第一次循环迭代,所以它会立即停止。

我们剩下的一个小问题是最后的输出句子不是很好:

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

理想情况下,我们想改变最后循环迭代的连接,以便我们在句子末尾没有逗号。 嗯,没有问题 - 我们可以很高兴地在我们的for循环中插入一个条件来处理这个特殊情况:

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

重要:使用for - 与所有循环一样,您必须确保初始化程序被迭代,以便最终达到退出条件。 如果没有,循环将永远继续,浏览器将强制它停止,否则会崩溃。 这称为无限循环

退出循环中断

如果要在所有迭代完成之前退出循环,可以使用 > break 语句。 当我们查看切换语句时,在switch语句中遇到一个情况时,我们在前一篇文章中已经满足了这一点 匹配输入表达式,break语句立即退出switch语句并移动到它之后的代码。

它与循环一样 - break 语句将立即退出循环,并使浏览器移动到其后的任何代码。

说我们想要通过一系列联系人和电话号码进行搜索,并只返回我们想要找到的号码? 首先是一些简单的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>

现在对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跳过迭代

继续语句的工作方式与 break / code>,但是不是完全打破循环,而是跳过循环的下一次迭代。 让我们看看另一个例子,它接受一个数字作为输入,并且只返回整数的正方形数字(整数)。

HTML基本上与上一个示例相同 - 一个简单的文本输入和一个用于输出的段落。 JavaScript大部分是相同的,虽然循环本身有点不同:

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中唯一可用的循环类型。 实际上有很多其他的,虽然你现在不需要了解所有这些,但值得看看一些其他人的结构,以便你可以以一种稍微不同的方式在工作中识别相同的功能。

首先,让我们看看 while 循环。 这个循环的语法如下:

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

  final-expression
}

除了在循环之前设置初始化器变量,并且final-expression包含在运行代码之后的循环内,而不是括号内包含这两个项目之外,它的工作方式与for循环非常相似。 退出条件包含在括号内,其前面有 while 关键字,而不是的

同样的三个项目仍然存在,它们仍然以与它们在for循环中相同的顺序定义 - 这是有意义的,因为您仍然必须定义初始化器,然后才能检查它是否已达到退出条件 ; 最终条件然后在循环中的代码已经运行(迭代已经完成)之后运行,这将仅在仍然未达到退出条件时发生。

让我们再看看我们的cats列表示例,但重写为使用while循环:

var i = 0;

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

  i++;
}

注意:此效果仍然与预期相同 - 请查看 while.html"class ="external">在GitHub上运行(也可以查看 /loops/while.html"class ="external">完整的源代码)。

do ... while 循环非常相似 ,但提供了while结构的变化:

initializer
do {
  // code to run

  final-expression
} while (exit-condition)

在这种情况下,初始化器再次来到循环开始之前。 do 关键字直接位于包含要运行的代码和final-expression的花括号之前。

这里的区别是退出条件在所有其他之后,包裹在括号中,并且在 while 关键字之前。 在 do ... while 循环中,花括号中的代码总是运行一次,然后再进行检查,看看是否应该再次执行(在while和for中,检查首先, 所以代码可能永远不会被执行)。

让我们重写我们的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 - 与所有循环一样,您必须确保初始化器被迭代,以便最终达到退出条件。 如果没有,循环将永远继续,浏览器将强制它停止,否则会崩溃。 这称为无限循环

主动学习:启动倒计时!

在本练习中,我们希望您打印出一个简单的启动倒计时到输出框,从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?

如果出错,您可以随时使用"重置"按钮重置示例。 如果你真的卡住,按"显示解决方案"看到一个解决方案。

主动学习:填写访客名单

在本练习中,我们希望您获取存储在数组中的名称列表,并将其放入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.

我们已经为您提供:

  • 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.

额外的奖金问题 - 成功完成上述任务后,您将留下两个名称列表,用逗号分隔,但它们将不整洁 - 每个结尾处都有一个逗号。 你能找出如何编写在每种情况下切分最后一个逗号的行,并添加一个完整的句点到底? 有关帮助,请查看有用的字符串方法文章。

如果出错,您可以随时使用"重置"按钮重置示例。 如果你真的卡住,按"显示解决方案"看到一个解决方案。

你应该使用哪个循环类型?

对于基本使用, while do ... while 循环在很大程度上是可互换的。 他们都可以用来解决相同的问题,你使用哪一个很大程度上取决于你的个人喜好 - 哪一个你发现最容易记住或最直观。 让我们再看看一下。

第一个 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 ,至少从开始,因为它可能是最容易记住一切 - 初始化,退出条件和最终表达式都必须整齐地放在括号中,所以它 很容易看到他们在哪里,并检查,你不是错过他们。

注意:还有其他循环类型/功能,这在高级/特殊情况下有用,超出了本文的范围。 如果您想进一步了解循环学习,请参阅我们的高级循环和迭代指南 a>。

结论

本文向您展示了基本概念,以及在JavaScript中循环代码时可用的不同选项。 你现在应该明确为什么循环是一个处理重复代码的好机制,并且在你自己的例子中使用它们。

如果您有任何不明白的地方,请随时阅读本文,或与我们联系以寻求帮助。

也可以看看

Making decisions in your code — conditionals
Functions — reusable blocks of code
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录
CSS

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }