JavaScript 中的基础数学 - 数字和运算符

在课程的这一点上,我们将讨论 JavaScript 中的数学 - 如何使用 operators 和其他功能来成功地操纵数字来执行我们的命令。

¥At this point in the course, we discuss math in JavaScript — how we can use operators and other features to successfully manipulate numbers to do our bidding.

先决条件: 对 HTML 和 CSS 有基本的了解,对 JavaScript 有了解。
目标: 熟悉 JavaScript 中的数学基础知识。

人人都爱数学

¥Everybody loves math

好吧,也许不是。我们中的一些人喜欢数学,一些人自从在学校必须学习乘法表和长除法以来就讨厌数学,而我们中的一些人则介于两者之间。但我们谁都不能否认数学是生活的基本组成部分,没有数学我们就走不了多远。当我们学习 JavaScript(或任何其他语言)编程时尤其如此 - 我们所做的很多事情都依赖于处理数值数据、计算新值等,因此你不会感到惊讶 JavaScript 拥有一组功能齐全的数学函数。

¥Okay, maybe not. Some of us like math, some of us have hated math ever since we had to learn multiplication tables and long division in school, and some of us sit somewhere in between the two. But none of us can deny that math is a fundamental part of life that we can't get very far without. This is especially true when we are learning to program JavaScript (or any other language for that matter) — so much of what we do relies on processing numerical data, calculating new values, and so on, that you won't be surprised to learn that JavaScript has a full-featured set of math functions available.

本文仅讨论你现在需要了解的基本部分。

¥This article discusses only the basic parts that you need to know now.

数字类型

¥Types of numbers

在编程中,即使是我们熟知的简陋的十进制数字系统也比你想象的要复杂。我们使用不同的术语来描述不同类型的十进制数,例如:

¥In programming, even the humble decimal number system that we all know so well is more complicated than you might think. We use different terms to describe different types of decimal numbers, for example:

  • 整数是没有小数部分的数字。它们可以是正数,也可以是负数,例如 10、400 或 -5。
  • 浮点数(float)具有小数点和小数位,例如 12.5 和 56.7786543。

我们甚至有不同类型的数字系统!十进制以 10 为基数(意味着每个数字使用 0-9),但我们也有类似的东西:

¥We even have different types of number systems! Decimal is base 10 (meaning it uses 0–9 in each digit), but we also have things like:

  • 二进制 - 计算机的最底层语言;0 和 1。
  • 八进制 - 基数 8,每个数字使用 0-7。
  • 十六进制 - 基数 16,在每个数字中使用 0-9,然后使用 a-f。你之前在设置 CSS 中的颜色 时可能遇到过这些数字。

在你开始担心你的大脑融化之前,就到此为止吧!首先,我们将在整个课程中坚持使用十进制数字;你很少会遇到需要开始考虑其他类型的情况(如果有的话)。

¥Before you start to get worried about your brain melting, stop right there! For a start, we are just going to stick to decimal numbers throughout this course; you'll rarely come across a need to start thinking about other types, if ever.

第二个好消息是,与其他一些编程语言不同,JavaScript 只有一种数字数据类型,包括整数和小数 - 你猜对了,Number。这意味着无论你在 JavaScript 中处理什么类型的数字,你都以完全相同的方式处理它们。

¥The second bit of good news is that unlike some other programming languages, JavaScript only has one data type for numbers, both integers and decimals — you guessed it, Number. This means that whatever type of numbers you are dealing with in JavaScript, you handle them in exactly the same way.

注意:实际上,JavaScript 有第二种数字类型 BigInt,用于非常非常大的整数。但出于本课程的目的,我们只关心 Number 值。

¥Note: Actually, JavaScript has a second number type, BigInt, used for very, very large integers. But for the purposes of this course, we'll just worry about Number values.

对我来说都是数字

¥It's all numbers to me

让我们快速玩一些数字来重新熟悉我们需要的基本语法。将下面列出的命令输入到你的 开发者工具 JavaScript 控制台.conf 文件中。

¥Let's quickly play with some numbers to reacquaint ourselves with the basic syntax we need. Enter the commands listed below into your developer tools JavaScript console.

  1. 首先,让我们声明几个变量并分别用整数和浮点数初始化它们,然后输入变量名称以检查一切是否正常:
    js
    const myInt = 5;
    const myFloat = 6.667;
    myInt;
    myFloat;
    
  2. 输入的数字值不带引号 - 在继续之前尝试声明并初始化更多包含数字的变量。
  3. 现在让我们检查两个原始变量是否具有相同的数据类型。JavaScript 中有一个名为 typeof 的运算符可以执行此操作。输入以下两行,如图所示:
    js
    typeof myInt;
    typeof myFloat;
    
    在这两种情况下,你都应该返回 "number" ——这对我们来说比不同的数字具有不同的数据类型要容易得多,而且我们必须以不同的方式处理它们。唷!

有用的数字方法

¥Useful Number methods

Number 对象是你将在 JavaScript 中使用的所有标准数字的一个实例,它有许多有用的方法可供你操作数字。我们不会在本文中详细介绍这些内容,因为我们希望将其保留为简单的介绍,目前仅介绍真正的基本要素;但是,一旦你阅读了该模块几次,就值得访问对象参考页面并了解有关可用内容的更多信息。

¥The Number object, an instance of which represents all standard numbers you'll use in your JavaScript, has a number of useful methods available on it for you to manipulate numbers. We don't cover these in detail in this article because we wanted to keep it as a simple introduction and only cover the real basic essentials for now; however, once you've read through this module a couple of times it is worth going to the object reference pages and learning more about what's available.

例如,要将数字四舍五入到固定的小数位数,请使用 toFixed() 方法。在浏览器的 console 中输入以下行:

¥For example, to round your number to a fixed number of decimal places, use the toFixed() method. Type the following lines into your browser's console:

js
const lotsOfDecimal = 1.766584958675746364;
lotsOfDecimal;
const twoDecimalPlaces = lotsOfDecimal.toFixed(2);
twoDecimalPlaces;

转换为数字数据类型

¥Converting to number data types

有时,你最终可能会得到一个存储为字符串类型的数字,这使得使用它执行计算变得困难。当数据输入 form 输入和 输入类型是文本. 输入时,最常发生这种情况。有一种方法可以解决这个问题 - 将字符串值传递到 Number() 构造函数中,以返回相同值的数字版本。

¥Sometimes you might end up with a number that is stored as a string type, which makes it difficult to perform calculations with it. This most commonly happens when data is entered into a form input, and the input type is text. There is a way to solve this problem — passing the string value into the Number() constructor to return a number version of the same value.

例如,尝试在控制台中输入以下几行:

¥For example, try typing these lines into your console:

js
let myNumber = "74";
myNumber += 3;

最终结果是 743,而不是 77,因为 myNumber 实际上被定义为字符串。你可以通过输入以下内容来测试:

¥You end up with the result 743, not 77, because myNumber is actually defined as a string. You can test this by typing in the following:

js
typeof myNumber;

要修复计算,你可以这样做:

¥To fix the calculation, you can do this:

js
let myNumber = "74";
myNumber = Number(myNumber) + 3;

结果如最初预期的那样为 77。

¥The result is then 77, as initially expected.

算术运算符

¥Arithmetic operators

算术运算符用于在 JavaScript 中执行数学计算:

¥Arithmetic operators are used for performing mathematical calculations in JavaScript:

运算符 名称 目的 示例
+ 添加 将两个数字相加。 XSPACE6 + 9
- 减法 从左边减去右边的数字。 XSPACE20 - 15
---STAR--- 乘法 将两个数字相乘。 XSPACE3 * 7
/ 分配 将左边的数字除以右边的数字。 XSPACE10 / 5
% 余数(有时称为模)

返回将左侧数字除以等于右侧数字的多个整数部分后剩下的余数。

XSPACE8 % 3(返回 2,因为 3 进入 8 两次,剩下 2)。

** 指数 base 数乘以 exponent 次方,即 base 数乘以自身 exponent 倍。 XSPACE5 ** 2(返回 XSPACE25,与 XSPACE5 * 5 相同)。

注意:有时你会看到涉及算术的数字被称为 operands

¥Note: You'll sometimes see numbers involved in arithmetic referred to as operands.

注意:有时你可能会看到使用旧的 Math.pow() 方法表示的指数,该方法的工作方式非常相似。例如,在 Math.pow(7, 3) 中,7 是底数,3 是指数,所以表达式的结果是 343Math.pow(7, 3) 相当于 7**3

¥Note: You may sometimes see exponents expressed using the older Math.pow() method, which works in a very similar way. For example, in Math.pow(7, 3), 7 is the base and 3 is the exponent, so the result of the expression is 343. Math.pow(7, 3) is equivalent to 7**3.

我们可能不需要教你如何做基础数学,但我们想测试你对所涉及语法的理解。尝试将以下示例输入到 开发者工具 JavaScript 控制台 中以熟悉语法。

¥We probably don't need to teach you how to do basic math, but we would like to test your understanding of the syntax involved. Try entering the examples below into your developer tools JavaScript console to familiarize yourself with the syntax.

  1. 首先尝试输入一些你自己的简单示例,例如
    js
    10 + 7;
    9 * 8;
    60 % 3;
    
  2. 你还可以尝试在变量内声明和初始化一些数字,并尝试在求和中使用这些数字 - 变量的行为与它们出于求和目的而保存的值完全相同。例如:
    js
    const num1 = 10;
    const num2 = 50;
    9 * num1;
    num1 ** 3;
    num2 / num1;
    
  3. 在本节的最后,尝试输入一些更复杂的表达式,例如:
    js
    5 + 10 * 3;
    (num2 % 9) * num1;
    num2 + num1 / 8 + 2;
    

最后一组计算的部分内容可能不会给出你所期望的结果;下面的部分很可能会给出原因的答案。

¥Parts of this last set of calculations might not give you quite the result you were expecting; the section below might well give the answer as to why.

运算符优先级

¥Operator precedence

让我们看一下上面的最后一个例子,假设 num2 保存值 50,num1 保存值 10(如上面最初所述):

¥Let's look at the last example from above, assuming that num2 holds the value 50 and num1 holds the value 10 (as originally stated above):

js
num2 + num1 / 8 + 2;

作为人类,你可能会将其读作 "50 加 10 等于 60",然后是 "8 加 2 等于 10",最后是 "60 除以 10 等于 6"。

¥As a human being, you may read this as "50 plus 10 equals 60", then "8 plus 2 equals 10", and finally "60 divided by 10 equals 6".

但浏览器执行 "10 除以 8 等于 1.25",然后执行 "50 加 1.25 加 2 等于 53.25"。

¥But the browser does "10 divided by 8 equals 1.25", then "50 plus 1.25 plus 2 equals 53.25".

这是因为运算符优先级 - 在计算计算结果(在编程中称为表达式)时,某些运算符先于其他运算符应用。JavaScript 中的运算符优先级与学校数学课上教授的运算符优先级相同 - 始终先进行乘法和除法,然后进行加法和减法(计算始终从左到右进行计算)。

¥This is because of operator precedence — some operators are applied before others when calculating the result of a calculation (referred to as an expression, in programming). Operator precedence in JavaScript is the same as is taught in math classes in school — multiply and divide are always done first, then add and subtract (the calculation is always evaluated from left to right).

如果要覆盖运算符优先级,可以在要首先显式处理的部分两边加上括号。因此,为了得到 6 的结果,我们可以这样做:

¥If you want to override operator precedence, you can put parentheses around the parts that you want to be explicitly dealt with first. So to get a result of 6, we could do this:

js
(num2 + num1) / (8 + 2);

尝试一下看看。

¥Try it and see.

注意:所有 JavaScript 运算符及其优先级的完整列表可以在 运算符优先级 中找到。

¥Note: A full list of all JavaScript operators and their precedence can be found in Operator precedence.

自增和自减运算符

¥Increment and decrement operators

有时你需要重复对数值变量值加一或减一。使用递增 (++) 和递减 (--) 运算符可以方便地完成此操作。我们在 第一次涉足 JavaScript 文章中的 "猜数字" 游戏中使用了 ++,当时我们向 guessCount 变量添加了 1,以跟踪用户在每回合后留下的猜测次数。

¥Sometimes you'll want to repeatedly add or subtract one to or from a numeric variable value. This can be conveniently done using the increment (++) and decrement (--) operators. We used ++ in our "Guess the number" game back in our first splash into JavaScript article, when we added 1 to our guessCount variable to keep track of how many guesses the user has left after each turn.

js
guessCount++;

让我们尝试在控制台中使用这些。首先,请注意,你不能将它们直接应用于数字,这可能看起来很奇怪,但我们正在为变量分配新的更新值,而不是对值本身进行操作。以下将返回错误:

¥Let's try playing with these in your console. For a start, note that you can't apply these directly to a number, which might seem strange, but we are assigning a variable a new updated value, not operating on the value itself. The following will return an error:

js
3++;

因此,你只能增加现有变量。尝试这个:

¥So, you can only increment an existing variable. Try this:

js
let num1 = 4;
num1++;

好吧,奇怪的事情 2 号!当你执行此操作时,你将看到返回值 4 — 这是因为浏览器返回当前值,然后递增变量。如果再次返回变量值,你可以看到它已增加:

¥Okay, strangeness number 2! When you do this, you'll see a value of 4 returned — this is because the browser returns the current value, then increments the variable. You can see that it's been incremented if you return the variable value again:

js
num1;

-- 也是如此:尝试以下操作

¥The same is true of -- : try the following

js
let num2 = 6;
num2--;
num2;

注意:你可以让浏览器以相反的方式执行此操作 - 递增/递减变量,然后返回值 - 通过将运算符放在变量的开头而不是末尾。再次尝试上面的示例,但这次使用 ++num1--num2

¥Note: You can make the browser do it the other way round — increment/decrement the variable then return the value — by putting the operator at the start of the variable instead of the end. Try the above examples again, but this time use ++num1 and --num2.

赋值运算符

¥Assignment operators

赋值运算符是将值赋给变量的运算符。我们已经使用了最基本的 = 多次 - 它将左侧的变量分配为右侧指定的值:

¥Assignment operators are operators that assign a value to a variable. We have already used the most basic one, =, loads of times — it assigns the variable on the left the value stated on the right:

js
let x = 3; // x contains the value 3
let y = 4; // y contains the value 4
x = y; // x now contains the same value y contains, 4

但还有一些更复杂的类型,它们提供了有用的快捷方式,使你的代码更整洁、更高效。最常见的如下:

¥But there are some more complex types, which provide useful shortcuts to keep your code neater and more efficient. The most common are listed below:

运算符 名称 目的 示例 快捷方式
+= 加法作业 将右侧的值与左侧的变量值相加,然后返回新的变量值 x += 4; x = x + 4;
-= 减法作业 从左边的变量值中减去右边的值,并返回新的变量值 x -= 3; x = x - 3;
*= 乘法作业 将左侧的变量值乘以右侧的值,并返回新的变量值 x *= 3; x = x * 3;
/= 分区分配 将左侧的变量值除以右侧的值,并返回新的变量值 x /= 5; x = x / 5;

尝试在控制台中输入上面的一些示例,以了解它们是如何工作的。在每种情况下,在输入第二行之前,看看你是否能猜出该值是什么。

¥Try typing some of the above examples into your console, to get an idea of how they work. In each case, see if you can guess what the value is before you type in the second line.

请注意,你可以很高兴地在每个表达式的右侧使用其他变量,例如:

¥Note that you can quite happily use other variables on the right-hand side of each expression, for example:

js
let x = 3; // x contains the value 3
let y = 4; // y contains the value 4
x *= y; // x now contains the value 12

注意:其他可用的赋值运算符 有很多,但这些是你现在应该学习的基础知识。

¥Note: There are lots of other assignment operators available, but these are the basic ones you should learn now.

主动学习:调整画布框的尺寸

¥Active learning: sizing a canvas box

在本练习中,你将操作一些数字和运算符来更改框的大小。该框是使用名为 Canvas API 的浏览器 API 绘制的。无需担心它是如何工作的 - 现在只需专注于数学即可。框的宽度和高度(以像素为单位)由变量 xy 定义,最初的值都为 50。

¥In this exercise, you will manipulate some numbers and operators to change the size of a box. The box is drawn using a browser API called the Canvas API. There is no need to worry about how this works — just concentrate on the math for now. The width and height of the box (in pixels) are defined by the variables x and y, which are initially both given a value of 50.

在新窗口中打开

¥**Open in new window**

在上面的可编辑代码框中,有两行标记有注释,我们希望你更新这些注释,以使框增大/缩小到特定大小,在每种情况下使用特定的运算符和/或值。让我们尝试以下操作:

¥In the editable code box above, there are two lines marked with a comment that we'd like you to update to make the box grow/shrink to certain sizes, using certain operators and/or values in each case. Let's try the following:

  • 更改计算 x 的行,使框仍为 50 像素宽,但 50 是使用数字 43 和 7 以及算术运算符计算的。
  • 更改计算 y 的行,使框的高度为 75 像素,但 75 是使用数字 25 和 3 以及算术运算符计算的。
  • 更改计算 x 的行,使框宽 250 像素,但 250 是使用两个数字和余数(模)运算符计算的。
  • 更改计算 y 的行,使框高 150 像素,但 150 是使用三个数字以及减法和除法运算符计算的。
  • 更改计算 x 的行,使框宽 200 像素,但 200 是使用数字 4 和赋值运算符计算的。
  • 更改计算 y 的行,使框高 200 像素,但 200 是使用数字 50 和 3、乘法运算符和加法赋值运算符计算的。

如果你完全搞乱了代码,请不要担心。你随时可以按“重置”按钮让一切恢复正常。正确回答完上述所有问题后,请随意尝试更多代码或创建自己的挑战。

¥Don't worry if you totally mess the code up. You can always press the Reset button to get things working again. After you've answered all the above questions correctly, feel free to play with the code some more or create your own challenges.

比较运算符

¥Comparison operators

有时我们想要运行真/假测试,然后根据测试的结果采取相应的行动 - 为此,我们使用比较运算符。

¥Sometimes we will want to run true/false tests, then act accordingly depending on the result of that test — to do this we use comparison operators.

运算符 名称 目的 示例
=== 严格平等 测试左右值是否相同 5 === 2 + 4
!== 严格非平等 测试左右值是否不相同 5 !== 2 + 3
< 少于 测试左侧值是否小于右侧值。 10 < 6
> 比...更棒 测试左侧值是否大于右侧值。 10 > 20
<= 小于或等于 测试左侧值是否小于或等于右侧值。 3 <= 2
>= 大于或等于 测试左侧值是否大于或等于右侧值。 5 >= 4

注意:你可能会看到有些人在相等和不相等的测试中使用 ==!=。这些是 JavaScript 中的有效运算符,但它们与 ===/!== 不同。以前的版本测试值是否相同,但不测试值的数据类型是否相同。后者的严格版本测试值及其数据类型的相等性。严格版本往往会导致更少的错误,因此我们建议你使用它们。

¥Note: You may see some people using == and != in their tests for equality and non-equality. These are valid operators in JavaScript, but they differ from ===/!==. The former versions test whether the values are the same but not whether the values' datatypes are the same. The latter, strict versions test the equality of both the values and their datatypes. The strict versions tend to result in fewer errors, so we recommend you use them.

如果你尝试在控制台中输入其中一些值,你将看到它们都返回 true/false 值 - 我们在上一篇文章中提到的那些布尔值。这些非常有用,因为它们允许我们在代码中做出决定,并且每次我们想要做出某种选择时都会使用它们。例如,布尔值可用于:

¥If you try entering some of these values in a console, you'll see that they all return true/false values — those booleans we mentioned in the last article. These are very useful, as they allow us to make decisions in our code, and they are used every time we want to make a choice of some kind. For example, booleans can be used to:

  • 根据功能是否打开或关闭在按钮上显示正确的文本标签
  • 如果游戏结束,则显示游戏结束消息;如果游戏获胜,则显示胜利消息
  • 根据节日季节显示正确的季节性问候语
  • 根据选择的缩放级别放大或缩小地图

当我们在以后的文章中查看条件语句时,我们将了解如何编写此类逻辑。现在,让我们看一个简单的例子:

¥We'll look at how to code such logic when we look at conditional statements in a future article. For now, let's look at a quick example:

html
<button>Start machine</button>
<p>The machine is stopped.</p>
js
const btn = document.querySelector("button");
const txt = document.querySelector("p");

btn.addEventListener("click", updateBtn);

function updateBtn() {
  if (btn.textContent === "Start machine") {
    btn.textContent = "Stop machine";
    txt.textContent = "The machine has started!";
  } else {
    btn.textContent = "Start machine";
    txt.textContent = "The machine is stopped.";
  }
}

在新窗口中打开

¥**Open in new window**

你可以看到 updateBtn() 函数内部使用了相等运算符。在这种情况下,我们不是测试两个数学表达式是否具有相同的值 - 我们正在测试按钮的文本内容是否包含某个字符串 - 但它仍然是相同的原理在工作。如果按下按钮时当前显示 "启动机器",我们将其标签更改为 "停机",并根据需要更新标签。如果按下按钮时当前显示 "停机",我们会再次将显示切换回来。

¥You can see the equality operator being used just inside the updateBtn() function. In this case, we are not testing if two mathematical expressions have the same value — we are testing whether the text content of a button contains a certain string — but it is still the same principle at work. If the button is currently saying "Start machine" when it is pressed, we change its label to "Stop machine", and update the label as appropriate. If the button is currently saying "Stop machine" when it is pressed, we swap the display back again.

注意:这种在两种状态之间切换的控件通常称为切换。它在一种状态和另一种状态之间切换 - 灯亮、灯灭等。

¥Note: Such a control that swaps between two states is generally referred to as a toggle. It toggles between one state and another — light on, light off, etc.

测试你的技能!

¥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: Math.

概括

¥Summary

在本文中,我们暂时介绍了你需要了解的有关 JavaScript 中数字的基本信息。在 JavaScript 学习的整个过程中,你会一次又一次地看到数字的使用,因此最好现在就解决这个问题。如果你是不喜欢数学的人之一,那么本章相当短,你可以放心。

¥In this article, we have covered the fundamental information you need to know about numbers in JavaScript, for now. You'll see numbers used again and again, all the way through your JavaScript learning, so it's a good idea to get this out of the way now. If you are one of those people that doesn't enjoy math, you can take comfort in the fact that this chapter was pretty short.

在下一篇文章中,我们将探讨文本以及 JavaScript 如何让我们操作它。

¥In the next article, we'll explore text and how JavaScript allows us to manipulate it.

注意:如果你确实喜欢数学并想了解有关如何在 JavaScript 中实现数学的更多信息,你可以在 MDN 的主要 JavaScript 部分找到更多详细信息。我们的 数字和日期表达式和运算符 文章是很好的起点。

¥Note: If you do enjoy math and want to read more about how it is implemented in JavaScript, you can find a lot more detail in MDN's main JavaScript section. Great places to start are our Numbers and dates and Expressions and operators articles.