JavaScript 中的基本數學 — 數值和運算子

在本課程的這一部分,我們將討論 JavaScript 中的數學——如何使用運算子和其他功能來成功地操縱數值以實現我們的目的。

預備知識 瞭解 HTMLCSS 基礎知識
學習成果
  • JavaScript 中的基本數值運算——加、減、乘、除。
  • 如果數值被定義為字串,它們就不是數值,並可能導致計算出錯。
  • 使用 Number() 將字串轉換為數值。
  • 運算子優先順序。
  • 遞增和遞減。
  • 賦值和比較運算子。
  • 基本的 Math 物件方法,例如 Math.random()Math.floor()Math.ceil()

人人都愛數學

好吧,也許不是。我們中的一些人喜歡數學,另一些人自從在學校學習乘法表和長除法後就討厭數學,還有一些人介於兩者之間。但我們誰也不能否認,數學是生活中不可或缺的一部分,沒有它我們寸步難行。當我們學習 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 控制檯中輸入下面列出的命令。

  1. 首先,讓我們宣告幾個變數,並分別用一個整數和一個浮點數來初始化它們,然後重新輸入變數名以檢查一切是否正常:

    js
    const myInt = 5;
    const myFloat = 6.667;
    myInt;
    myFloat;
    
  2. 數值在輸入時不需要引號——在繼續之前,嘗試宣告並初始化另外幾個包含數值的變數。

  3. 現在讓我們檢查一下我們最初的兩個變數是否是相同的資料型別。JavaScript 中有一個名為 typeof 的運算子可以做到這一點。如下所示輸入以下兩行:

    js
    typeof myInt;
    typeof myFloat;
    

    兩種情況下都應該返回 "number"——這比不同型別的數值有不同的資料型別,需要用不同方式處理要簡單得多。太好了!

有用的 Number 方法

Number 物件的一個例項代表了你在 JavaScript 中會用到的所有標準數值,它上面有許多有用的方法可以用來運算元值。我們在本文中不會詳細介紹這些方法,因為我們希望將其作為入門介紹,目前只涵蓋真正的基礎知識;但是,在你讀完這個模組幾次後,值得去檢視物件參考頁面,瞭解更多可用的方法。

例如,要將你的數值四捨五入到固定的小數位數,請使用 toFixed() 方法。在你的瀏覽器的控制檯中輸入以下幾行:

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

轉換為數值資料型別

有時你可能會遇到以字串型別儲存的數值,這使得對其進行計算變得困難。這最常發生在資料被輸入到表單輸入框中,且輸入框型別為文字時。有一個解決方法——將字串值傳入 Number() 建構函式,以返回相同值的數值版本。

例如,嘗試在你的控制檯中輸入這些行:

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

你得到的結果是 743,而不是 77,因為 myNumber 實際上被定義為一個字串。你可以透過輸入以下內容來測試:

js
typeof myNumber;

要修復這個計算,你可以這樣做:

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

結果就是 77,如最初預期的那樣。

算術運算子

算術運算子用於在 JavaScript 中執行數學計算。

運算子 名稱 用途 示例
+ 加法 將兩個數相加。 6 + 9
- 減法 左邊的數減去右邊的數。 20 - 15
* 乘法 將兩個數相乘。 3 * 7
/ 除法 左邊的數除以右邊的數。 10 / 5
% 餘數(有時稱為模)

返回左邊的數除以右邊的數後,剩餘的餘數。

8 % 3(返回 2,因為 3 除 8 得 2,餘 2)。

** 將一個底數提升到指數次冪,即底數自乘指數次。 5 ** 2(返回 25,與 5 * 5 相同)。

備註:你有時會看到參與算術運算的數被稱為運算元

備註:你有時可能會看到使用舊的 Math.pow() 方法來表示冪運算,它的工作方式非常相似。例如,在 Math.pow(7, 3) 中,7 是底數,3 是指數,所以表示式的結果是 343Math.pow(7, 3) 等同於 7**3

我們可能不需要教你如何做基礎數學,但我們想測試你對所涉及語法的理解。嘗試在你的開發者工具的 JavaScript 控制檯中輸入以下示例,以熟悉語法。

  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;
    

最後一組計算的某些部分可能沒有給你預期的結果;下面的部分很可能會解釋為什麼。

運算子優先順序

讓我們看一下上面最後一個例子,假設 num2 的值是 50,num1 的值是 10(如上文最初所述):

js
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,我們可以這樣做:

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

嘗試在控制檯中輸入上一行來測試一下。

備註:所有 JavaScript 運算子及其優先順序的完整列表可以在運算子優先順序中找到。

遞增和遞減運算子

有時你會想對一個數值變數重複地加一或減一。這可以方便地使用遞增 (++) 和遞減 (--) 運算子來完成。我們在初探 JavaScript 文章中的“猜數字”遊戲中使用了 ++,當時我們給 guessCount 變數加 1,以跟蹤使用者每輪後還剩下多少次猜測機會。

js
guessCount++;

讓我們在你的控制檯中試一下這些。首先,請注意你不能將它們直接應用於一個數,這可能看起來很奇怪,但我們是在給一個變數賦一個新的更新值,而不是對值本身進行操作。以下程式碼會返回一個錯誤:

js
3++;

所以,你只能遞增一個已存在的變數。試試這個:

js
let num1 = 4;
num1++;

好了,第二個奇怪之處!當你這樣做時,你會看到返回值為 4——這是因為瀏覽器會返回當前值,然後再遞增變數。如果你再次返回變數的值,你就會看到它已經被遞增了:

js
num1;

-- 也是如此:嘗試以下程式碼:

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

備註:你可以讓瀏覽器反過來做——先遞增/遞減變數,然後再返回值——方法是將運算子放在變數的開頭而不是末尾。再次嘗試上面的例子,但這次使用 ++num1--num2

賦值運算子

賦值運算子是給變數賦值的運算子。我們已經多次使用了最基本的一個,=——它將右邊的值賦給左邊的變數:

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

但還有一些更復雜的型別,它們提供了有用的快捷方式,使你的程式碼更整潔、更高效。最常見的如下所示:

運算子 名稱 用途 示例 快捷方式
+= 加法賦值 將右邊的值加到左邊變數的值上,然後返回新的變數值 x += 4; x = x + 4;
-= 減法賦值 從左邊變數的值中減去右邊的值,並返回新的變數值 x -= 3; x = x - 3;
*= 乘法賦值 將左邊變數的值乘以右邊的值,並返回新的變數值 x *= 3; x = x * 3;
/= 除法賦值 將左邊變數的值除以右邊的值,並返回新的變數值 x /= 5; x = x / 5;

嘗試在你的控制檯中輸入一些上面的例子,以瞭解它們是如何工作的。在每種情況下,看看你是否能在輸入第二行之前猜出值是多少。

注意,你完全可以在每個表示式的右側使用其他變數,例如:

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

備註:還有許多其他可用的賦值運算子,但這些是你現在應該學習的基礎。

調整畫布盒子的大小

在這個練習中,你將操作一些數值和運算子來改變一個盒子的大小。這個盒子是使用一個名為 Canvas API 的瀏覽器 API 繪製的。無需擔心它是如何工作的——現在只需專注於數學部分。盒子的寬度和高度(以畫素為單位)由變數 xy 定義,它們最初都被賦予了 50 的值。

js
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 值——就是我們在上一篇文章中提到的布林值。這些非常有用,因為它們允許我們在程式碼中做決策,並且每當我們想做某種選擇時都會用到它們。例如,布林值可以用來:

  • 根據某個功能是開啟還是關閉,在按鈕上顯示正確的文字標籤
  • 如果遊戲結束則顯示遊戲結束訊息,如果遊戲獲勝則顯示勝利訊息
  • 根據是什麼節日季節顯示正確的季節性問候
  • 根據選擇的縮放級別放大或縮小地圖

我們將在未來的文章中學習條件語句時,看看如何編寫這樣的邏輯。現在,讓我們看一個快速的例子:

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.";
  }
}

你可以在 updateBtn() 函式內部看到相等運算子的使用。在這種情況下,我們不是在測試兩個數學表示式的值是否相同——我們是在測試按鈕的文字內容是否包含某個特定的字串——但其工作原理是相同的。如果按鈕在被按下時當前顯示“啟動機器”,我們會將其標籤更改為“停止機器”,並相應地更新標籤。如果按鈕在被按下時當前顯示“停止機器”,我們會將顯示切換回來。

備註:這種在兩種狀態之間切換的控制元件通常被稱為開關(toggle)。它在一種狀態和另一種狀態之間切換——燈開,燈關,等等。

總結

在本文中,我們已經涵蓋了你目前需要了解的關於 JavaScript 中數值的基礎資訊。在你的 JavaScript 學習過程中,你會一次又一次地看到數值的使用,所以現在把這部分搞清楚是個好主意。如果你是那些不喜歡數學的人之一,你可以感到欣慰的是,這一章相當簡短。

在下一篇文章中,我們將提供一些測試,你可以用它們來檢查你對這些資訊的理解和掌握程度。

另見