函数返回值

我们要讨论关于函数的最后一个基本概念 - 返回值。有些函数不会返回有效值,但其他函数会返回有效值。了解它们的值是什么、如何在代码中使用它们以及如何使函数返回有用的值非常重要。我们将在下面介绍所有这些内容。

¥There's one last essential concept about functions for us to discuss — return values. Some functions don't return a significant value, but others do. It's important to understand what their values are, how to use them in your code, and how to make functions return useful values. We'll cover all of these below.

先决条件:

对 HTML 和 CSS、 JavaScript 第一步函数 - 可重用的代码块 有基本了解。

目标: 了解函数返回值以及如何使用它们。

什么是返回值?

¥What are return values?

返回值顾名思义就是函数完成时返回的值。你已经多次遇到返回值,尽管你可能没有明确考虑过它们。

¥Return values are just what they sound like — the values that a function returns when it completes. You've already met return values several times, although you may not have thought about them explicitly.

让我们回到一个熟悉的示例(来自本系列中的 上一篇文章):

¥Let's return to a familiar example (from a previous article in this series):

js
const myText = "The weather is cold";
const newString = myText.replace("cold", "warm");
console.log(newString); // Should print "The weather is warm"
// the replace() string function takes a string,
// replaces one substring with another, and returns
// a new string with the replacement made

replace() 函数在 myText 字符串上调用,并传递两个参数:

¥The replace() function is invoked on the myText string, and is passed two parameters:

  • 要查找的子字符串 ('cold')
  • 替换为 ('warm') 的字符串

当函数完成(完成运行)时,它返回一个值,该值是经过替换的新字符串。在上面的代码中,这个返回值的结果保存在变量 newString 中。

¥When the function completes (finishes running), it returns a value, which is a new string with the replacement made. In the code above, the result of this return value is saved in the variable newString.

如果你查看 replace() 函数 MDN 参考页,你将看到名为 返回值 的部分。了解和理解函数返回哪些值非常有用,因此我们尝试尽可能包含这些信息。

¥If you look at the replace() function MDN reference page, you'll see a section called return value. It is very useful to know and understand what values are returned by functions, so we try to include this information wherever possible.

有些函数不返回任何值。(在这些情况下,我们的参考页将返回值列为 voidundefined。)例如,在上一篇文章中我们构建的 displayMessage() 函数中,调用该函数时没有返回具体值。它只是让一个框出现在屏幕上的某个地方 - 就是这样!

¥Some functions don't return any value. (In these cases, our reference pages list the return value as void or undefined.) For example, in the displayMessage() function we built in the previous article, no specific value is returned when the function is invoked. It just makes a box appear somewhere on the screen — that's it!

通常,当函数是某种计算的中间步骤时,会使用返回值。你想要获得最终结果,其中涉及需要通过函数计算的一些值。函数计算值后,可以返回结果,以便将其存储在变量中;你可以在下一阶段的计算中使用该变量。

¥Generally, a return value is used where the function is an intermediate step in a calculation of some kind. You want to get to a final result, which involves some values that need to be calculated by a function. After the function calculates the value, it can return the result so it can be stored in a variable; and you can use this variable in the next stage of the calculation.

在你自己的函数中使用返回值

¥Using return values in your own functions

要从自定义函数返回值,你需要使用 return 关键字。我们最近在 random-canvas-circles.html 示例中看到了这一点。我们的 draw() 函数在 HTML <canvas> 上的某处绘制 100 个随机圆圈:

¥To return a value from a custom function, you need to use the return keyword. We saw this in action recently in our random-canvas-circles.html example. Our draw() function draws 100 random circles somewhere on an HTML <canvas>:

js
function draw() {
  ctx.clearRect(0, 0, WIDTH, HEIGHT);
  for (let i = 0; i < 100; i++) {
    ctx.beginPath();
    ctx.fillStyle = "rgb(255 0 0 / 50%)";
    ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);
    ctx.fill();
  }
}

在每次循环迭代中,对 random() 函数进行三次调用,分别为当前圆的 x 坐标、y 坐标和半径生成随机值。random() 函数接受一个参数(一个整数),并返回 0 和该数字之间的一个整数随机数。它看起来像这样:

¥Inside each loop iteration, three calls are made to the random() function, to generate a random value for the current circle's x-coordinate, y-coordinate, and radius, respectively. The random() function takes one parameter — a whole number — and returns a whole random number between 0 and that number. It looks like this:

js
function random(number) {
  return Math.floor(Math.random() * number);
}

这可以写成如下:

¥This could be written as follows:

js
function random(number) {
  const result = Math.floor(Math.random() * number);
  return result;
}

但第一个版本编写起来更快,也更紧凑。

¥But the first version is quicker to write, and more compact.

每次调用该函数时,我们都会返回计算结果 Math.floor(Math.random() * number)。该返回值出现在调用函数的位置,并且代码继续。

¥We are returning the result of the calculation Math.floor(Math.random() * number) each time the function is called. This return value appears at the point the function was called, and the code continues.

因此,当你执行以下命令时:

¥So when you execute the following:

js
ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);

如果三个 random() 调用分别返回值 50020035,则该行实际上会像这样运行:

¥If the three random() calls return the values 500, 200, and 35, respectively, the line would actually be run as if it were this:

js
ctx.arc(500, 200, 35, 0, 2 * Math.PI);

在执行该行本身之前,首先运行该行上的函数调用,并用它们的返回值替换该函数调用。

¥The function calls on the line are run first, and their return values are substituted for the function calls, before the line itself is then executed.

主动学习:我们自己的返回值函数

¥Active learning: our own return value function

让我们尝试编写我们自己的具有返回值的函数。

¥Let's have a go at writing our own functions featuring return values.

  1. 从 GitHub 制作 function-library.html 文件的本地副本。这是一个简单的 HTML 页面,包含一个文本 <input> 字段和一个段落。还有一个 <script> 元素,我们在其中存储了对两个变量中两个 HTML 元素的引用。此页面将允许你在文本框中输入一个数字,并在下面显示与其相关的不同数字。
  2. 在现有两行下方的 <script> 元素中添加一些有用的函数:
    js
    function squared(num) {
      return num * num;
    }
    
    function cubed(num) {
      return num * num * num;
    }
    
    function factorial(num) {
      if (num < 0) return undefined;
      if (num === 0) return 1;
      let x = num - 1;
      while (x > 1) {
        num *= x;
        x--;
      }
      return num;
    }
    
    squared()cubed() 函数相当明显 - 它们返回作为参数给出的数字的平方或立方。factorial() 函数返回给定数字的 factorial
  3. 通过在现有函数下方添加以下事件处理程序,包括一种打印有关文本输入中输入的数字信息的方法:
    js
    input.addEventListener("change", () => {
      const num = parseFloat(input.value);
      if (isNaN(num)) {
        para.textContent = "You need to enter a number!";
      } else {
        para.textContent = `${num} squared is ${squared(num)}. `;
        para.textContent += `${num} cubed is ${cubed(num)}. `;
        para.textContent += `${num} factorial is ${factorial(num)}. `;
      }
    });
    
  4. 保存你的代码,将其加载到浏览器中,然后尝试一下。

下面是对上面第 3 步中的 addEventListener 函数的一些解释:

¥Here are some explanations for the addEventListener function in step 3 above:

  • 通过向 change 事件添加监听器,只要文本输入上触发 change 事件,即在文本 input 中输入新值并提交时(例如,输入一个值,然后取消输入焦点),此函数就会运行 按 TabReturn)。当该匿名函数运行时,input 中的值存储在 num 常量中。
  • 如果输入的值不是数字,if 语句将打印一条错误消息。该条件检查表达式 isNaN(num) 是否返回 trueisNaN() 函数测试 num 值是否不是数字 - 如果是,则返回 true,如果不是,则返回 false
  • 如果条件返回 false,则 num 值是一个数字,并且该函数在段落元素内打印出一个句子,说明该数字的平方、立方和阶乘值。该语句调用 squared()cubed()factorial() 函数来计算所需的值。

注意:如果你在使示例正常工作时遇到困难,请对照 GitHub 上的完成版本(也包括 看到它实时运行)检查你的代码,或向我们寻求帮助。

¥Note: If you have trouble getting the example to work, check your code against the finished version on GitHub (see it running live also), or ask us for help.

现在轮到你了!

¥Now it's your turn!

此时,我们希望你尝试编写一些自己的函数并将它们添加到库中。数字的平方根或立方根怎么样?或者给定半径的圆的周长?

¥At this point, we'd like you to have a go at writing out a couple of functions of your own and adding them to the library. How about the square or cube root of the number? Or the circumference of a circle with a given radius?

一些与功能相关的额外提示:

¥Some extra function-related tips:

  • 看一下将错误处理写入函数的另一个示例。通常最好检查是否验证了所有必要的参数,以及是否为任何可选参数提供了某种默认值。这样,你的程序将不太可能抛出错误。
  • 考虑一下创建函数库的想法。当你进一步进入编程职业生涯时,你将开始一遍又一遍地做同样的事情。创建自己的实用函数库来完成这些事情是一个好主意。你可以将它们复制到新代码中,甚至可以将它们应用到 HTML 页面中任何需要的地方。

测试你的技能!

¥Test your skills!

你已读完本文,但你还记得最重要的信息吗?在继续之前,你可以找到一些进一步的测试来验证你是否已保留此信息 - 请参阅 测试你的技能:函数

¥You've reached the end of this article, but can you remember the most important information? You can find some further tests to verify that you've retained this information before you move on — see Test your skills: Functions.

结论

¥Conclusion

现在我们知道了 - 函数很有趣,非常有用,尽管关于它们的语法和功能有很多值得讨论的地方,但它们还是相当容易理解的。

¥So there we have it — functions are fun, very useful, and although there's a lot to talk about in regards to their syntax and functionality, they are fairly understandable.

如果有什么不明白的地方,欢迎再通读一遍文章,或者 联系我们 寻求帮助。

¥If there is anything you didn't understand, feel free to read through the article again, or contact us to ask for help.

也可以看看

¥See also

  • 函数深入 — 涵盖更高级功能相关信息的详细指南。
  • JavaScript 中的回调函数 — 一种常见的 JavaScript 模式是将一个函数作为参数传递给另一个函数。然后在第一个函数内调用它。这有点超出了本课程的范围,但值得不久之后研究。