人人都爱数学
好吧,也许不是。我们中的一些人喜欢数学,另一些人自从在学校学习乘法表和长除法后就讨厌数学,还有一些人介于两者之间。但我们谁也不能否认,数学是生活中不可或缺的一部分,没有它我们寸步难行。当我们学习 JavaScript(或任何其他语言)编程时尤其如此——我们所做的很多事情都依赖于处理数值数据、计算新值等等,所以当你了解到 JavaScript 拥有一整套功能齐全的数学函数时,你不会感到惊讶。
本文只讨论你现在需要了解的基础部分。
数值的类型
在编程中,即使是我们都熟知的普通十进制数系统,也比你想象的要复杂。我们用不同的术语来描述不同类型的十进制数,例如:
- 整数是没有小数部分的数。它们可以是正数或负数,例如 10、400 或 -5。
- 浮点数(floats)有小数点和小数位,例如 12.5 和 56.7786543。
我们甚至有不同类型的数制!十进制是基数为 10(意味着每位使用 0-9),但我们还有类似以下的数制:
- 二进制——计算机的最低级语言;0 和 1。
- 八进制——基数为 8,每位使用 0-7。
- 十六进制——基数为 16,每位使用 0-9 然后是 a-f。你可能在 CSS 中设置颜色时遇到过这些数。
在你开始担心大脑要融化之前,请就此打住!首先,在本课程中,我们将只使用十进制数;你很少会需要考虑其他类型的数,如果真的有的话。
第二个好消息是,与其他一些编程语言不同,JavaScript 只有一种数值数据类型,用于表示整数和浮点数——你猜对了,就是 Number。这意味着无论你在 JavaScript 中处理何种类型的数值,处理它们的方式都完全相同。
备注:实际上,JavaScript 还有第二种数值类型,BigInt,用于表示非常非常大的整数。但就本课程而言,我们只需关心 Number 类型的值。
对我来说都是数值
让我们快速地玩一下数值,以重新熟悉我们需要的基本语法。在你的浏览器开发者工具的 JavaScript 控制台中输入下面列出的命令。
-
首先,让我们声明几个变量,并分别用一个整数和一个浮点数来初始化它们,然后重新输入变量名以检查一切是否正常:
jsconst myInt = 5; const myFloat = 6.667; myInt; myFloat; -
数值在输入时不需要引号——在继续之前,尝试声明并初始化另外几个包含数值的变量。
-
现在让我们检查一下我们最初的两个变量是否是相同的数据类型。JavaScript 中有一个名为
typeof的运算符可以做到这一点。如下所示输入以下两行:jstypeof myInt; typeof myFloat;两种情况下都应该返回
"number"——这比不同类型的数值有不同的数据类型,需要用不同方式处理要简单得多。太好了!
有用的 Number 方法
Number 对象的一个实例代表了你在 JavaScript 中会用到的所有标准数值,它上面有许多有用的方法可以用来操作数值。我们在本文中不会详细介绍这些方法,因为我们希望将其作为入门介绍,目前只涵盖真正的基础知识;但是,在你读完这个模块几次后,值得去查看对象参考页面,了解更多可用的方法。
例如,要将你的数值四舍五入到固定的小数位数,请使用 toFixed() 方法。在你的浏览器的控制台中输入以下几行:
const lotsOfDecimal = 1.7665849587;
lotsOfDecimal;
const twoDecimalPlaces = lotsOfDecimal.toFixed(2);
twoDecimalPlaces;
转换为数值数据类型
有时你可能会遇到以字符串类型存储的数值,这使得对其进行计算变得困难。这最常发生在数据被输入到表单输入框中,且输入框类型为文本时。有一个解决方法——将字符串值传入 Number() 构造函数,以返回相同值的数值版本。
例如,尝试在你的控制台中输入这些行:
let myNumber = "74";
myNumber += 3;
你得到的结果是 743,而不是 77,因为 myNumber 实际上被定义为一个字符串。你可以通过输入以下内容来测试:
typeof myNumber;
要修复这个计算,你可以这样做:
let myNumber = "74";
myNumber = Number(myNumber) + 3;
结果就是 77,如最初预期的那样。
算术运算符
算术运算符用于在 JavaScript 中执行数学计算。
| 运算符 | 名称 | 用途 | 示例 |
|---|---|---|---|
+ |
加法 | 将两个数相加。 | 6 + 9 |
- |
减法 | 左边的数减去右边的数。 | 20 - 15 |
* |
乘法 | 将两个数相乘。 | 3 * 7 |
/ |
除法 | 左边的数除以右边的数。 | 10 / 5 |
% |
余数(有时称为模) |
返回左边的数除以右边的数后,剩余的余数。 |
|
** |
幂 | 将一个底数提升到指数次幂,即底数自乘指数次。 |
5 ** 2(返回 25,与 5 * 5 相同)。 |
备注:你有时会看到参与算术运算的数被称为操作数。
备注:你有时可能会看到使用旧的 Math.pow() 方法来表示幂运算,它的工作方式非常相似。例如,在 Math.pow(7, 3) 中,7 是底数,3 是指数,所以表达式的结果是 343。Math.pow(7, 3) 等同于 7**3。
我们可能不需要教你如何做基础数学,但我们想测试你对所涉及语法的理解。尝试在你的开发者工具的 JavaScript 控制台中输入以下示例,以熟悉语法。
-
首先尝试输入一些你自己的简单示例,例如:
js10 + 7; 9 * 8; 60 % 3; -
你也可以尝试在变量中声明和初始化一些数值,并尝试在求和中使用它们——在求和中,这些变量的行为将完全等同于它们所持有的值。例如:
jsconst num1 = 10; const num2 = 50; 9 * num1; num1 ** 3; num2 / num1; -
本节最后,尝试输入一些更复杂的表达式,例如:
js5 + 10 * 3; (num2 % 9) * num1; num2 + num1 / 8 + 2;
最后一组计算的某些部分可能没有给你预期的结果;下面的部分很可能会解释为什么。
运算符优先级
让我们看一下上面最后一个例子,假设 num2 的值是 50,num1 的值是 10(如上文最初所述):
num2 + num1 / 8 + 2;
作为人类,你可能会将其读作“50 加 10 等于 60”,然后“8 加 2 等于 10”,最后“60 除以 10 等于 6”。
但浏览器会先算“10 除以 8 等于 1.25”,然后“50 加 1.25 加 2 等于 53.25”。
这是因为运算符优先级——在计算一个计算结果(在编程中称为表达式)时,某些运算符会比其他运算符先被应用。JavaScript 中的运算符优先级与学校数学课上教的一样——乘法和除法总是先做,然后是加法和减法(计算总是从左到右进行)。
如果你想覆盖运算符优先级,你可以用括号括起你希望优先处理的部分。所以要得到结果 6,我们可以这样做:
(num2 + num1) / (8 + 2);
尝试在控制台中输入上一行来测试一下。
备注:所有 JavaScript 运算符及其优先级的完整列表可以在运算符优先级中找到。
递增和递减运算符
有时你会想对一个数值变量重复地加一或减一。这可以方便地使用递增 (++) 和递减 (--) 运算符来完成。我们在初探 JavaScript 文章中的“猜数字”游戏中使用了 ++,当时我们给 guessCount 变量加 1,以跟踪用户每轮后还剩下多少次猜测机会。
guessCount++;
让我们在你的控制台中试一下这些。首先,请注意你不能将它们直接应用于一个数,这可能看起来很奇怪,但我们是在给一个变量赋一个新的更新值,而不是对值本身进行操作。以下代码会返回一个错误:
3++;
所以,你只能递增一个已存在的变量。试试这个:
let num1 = 4;
num1++;
好了,第二个奇怪之处!当你这样做时,你会看到返回值为 4——这是因为浏览器会返回当前值,然后再递增变量。如果你再次返回变量的值,你就会看到它已经被递增了:
num1;
-- 也是如此:尝试以下代码:
let num2 = 6;
num2--;
num2;
备注:你可以让浏览器反过来做——先递增/递减变量,然后再返回值——方法是将运算符放在变量的开头而不是末尾。再次尝试上面的例子,但这次使用 ++num1 和 --num2。
赋值运算符
赋值运算符是给变量赋值的运算符。我们已经多次使用了最基本的一个,=——它将右边的值赋给左边的变量:
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
但还有一些更复杂的类型,它们提供了有用的快捷方式,使你的代码更整洁、更高效。最常见的如下所示:
| 运算符 | 名称 | 用途 | 示例 | 快捷方式 |
|---|---|---|---|---|
+= |
加法赋值 | 将右边的值加到左边变量的值上,然后返回新的变量值 | x += 4; |
x = x + 4; |
-= |
减法赋值 | 从左边变量的值中减去右边的值,并返回新的变量值 | x -= 3; |
x = x - 3; |
*= |
乘法赋值 | 将左边变量的值乘以右边的值,并返回新的变量值 | x *= 3; |
x = x * 3; |
/= |
除法赋值 | 将左边变量的值除以右边的值,并返回新的变量值 | x /= 5; |
x = x / 5; |
尝试在你的控制台中输入一些上面的例子,以了解它们是如何工作的。在每种情况下,看看你是否能在输入第二行之前猜出值是多少。
注意,你完全可以在每个表达式的右侧使用其他变量,例如:
let x = 3; // x contains the value 3
let y = 4; // y contains the value 4
x *= y; // x now contains the value 12
备注:还有许多其他可用的赋值运算符,但这些是你现在应该学习的基础。
调整画布盒子的大小
在这个练习中,你将操作一些数值和运算符来改变一个盒子的大小。这个盒子是使用一个名为 Canvas API 的浏览器 API 绘制的。无需担心它是如何工作的——现在只需专注于数学部分。盒子的宽度和高度(以像素为单位)由变量 x 和 y 定义,它们最初都被赋予了 50 的值。
const canvas = document.getElementById("canvas");
const para = document.querySelector("p");
const ctx = canvas.getContext("2d");
// Edit the following two lines ONLY
let x = 50;
let y = 50;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "green";
ctx.fillRect(10, 10, x, y);
para.textContent = `The rectangle is ${x}px wide and ${y}px high.`;
通过点击“运行”按钮在 MDN Playground 中打开以上示例,然后按照下面的说明列表,在每种情况下使用特定的运算符和/或值,使盒子放大/缩小到特定尺寸:
- 更改计算
x的那一行,使盒子的宽度仍然是50px,但是 50 是使用数字 43 和 7 以及一个算术运算符计算出来的。 - 更改计算
y的那一行,使盒子的高度是75px,但是 75 是使用数字 25 和 3 以及一个算术运算符计算出来的。 - 更改计算
x的那一行,使盒子的宽度是100px,但是 100 是使用三个数字以及减法和除法运算符计算出来的。 - 更改计算
y的那一行,使盒子的高度是200px,但是 200 是使用数字 2 和x以及乘法运算符计算出来的。
如果把代码弄乱了也不用担心。你随时可以按下“重置”按钮重新开始。
比较运算符
有时我们会想运行真/假测试,然后根据测试的结果采取相应的行动——要做到这一点,我们使用比较运算符。
| 运算符 | 名称 | 用途 | 示例 |
|---|---|---|---|
=== |
严格相等 | 测试左值和右值是否完全相同 | 5 === 2 + 4 |
!== |
严格不相等 | 测试左值和右值是否不完全相同 | 5 !== 2 + 3 |
< |
小于 | 测试左值是否小于右值。 | 10 < 6 |
> |
大于 | 测试左值是否大于右值。 | 10 > 20 |
<= |
小于或等于 | 测试左值是否小于或等于右值。 | 3 <= 2 |
>= |
大于或等于 | 测试左值是否大于或等于右值。 | 5 >= 4 |
备注:你可能会看到一些人在他们的相等和不相等测试中使用 == 和 !=。这些在 JavaScript 中是有效的运算符,但它们与 ===/!== 不同。前一种版本测试值是否相同,但不测试值的数据类型是否相同。后一种严格版本则同时测试值和数据类型的相等性。严格版本往往能减少错误,所以我们推荐你使用它们。
如果你尝试在控制台中输入其中一些值,你会看到它们都返回 true/false 值——就是我们在上一篇文章中提到的布尔值。这些非常有用,因为它们允许我们在代码中做决策,并且每当我们想做某种选择时都会用到它们。例如,布尔值可以用来:
- 根据某个功能是开启还是关闭,在按钮上显示正确的文本标签
- 如果游戏结束则显示游戏结束消息,如果游戏获胜则显示胜利消息
- 根据是什么节日季节显示正确的季节性问候
- 根据选择的缩放级别放大或缩小地图
我们将在未来的文章中学习条件语句时,看看如何编写这样的逻辑。现在,让我们看一个快速的例子:
<button>Start machine</button>
<p>The machine is stopped.</p>
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.";
}
}
你可以在 updateBtn() 函数内部看到相等运算符的使用。在这种情况下,我们不是在测试两个数学表达式的值是否相同——我们是在测试按钮的文本内容是否包含某个特定的字符串——但其工作原理是相同的。如果按钮在被按下时当前显示“启动机器”,我们会将其标签更改为“停止机器”,并相应地更新标签。如果按钮在被按下时当前显示“停止机器”,我们会将显示切换回来。
备注:这种在两种状态之间切换的控件通常被称为开关(toggle)。它在一种状态和另一种状态之间切换——灯开,灯关,等等。
总结
在本文中,我们已经涵盖了你目前需要了解的关于 JavaScript 中数值的基础信息。在你的 JavaScript 学习过程中,你会一次又一次地看到数值的使用,所以现在把这部分搞清楚是个好主意。如果你是那些不喜欢数学的人之一,你可以感到欣慰的是,这一章相当简短。
在下一篇文章中,我们将提供一些测试,你可以用它们来检查你对这些信息的理解和掌握程度。