初次接觸Javascript

由於本文件沒有此語言的翻譯版本,您閱讀的是英文版的內容。 幫助我們翻譯這篇文章!

目前你已經學會了一些JavaScript的理論,以及你能用它做些什麼。我們現在要透過一個完整的實際範例給你一個JavaScript基本功能的速成班。你將能一步一步地做出一個簡單的"猜數字"遊戲

先備知識: 基礎的電腦知識 , 有基礎的 HTML 跟 CSS 知識 ,
還有知道 JavaScript 是甚麼 .
目標: 獲得第一次寫 JavaScript 的經驗 ,
還有知道最基礎的 JavaScript 程式該怎麼寫 .

並不會要求你馬上就能仔細地了解所有程式碼 — 目前我們只是想介紹一些概觀,並向你介紹一些關於JavaScript(以及其他程式語言)如何運作的知識。在接下來的章節你將會更仔細地瞭解這些功能!

Note: 你會在 JavaScript 看到許多跟其他程式語言一樣的特徵 — functions , loops 之類的 ,雖然程式語法看起來有差 ,但概念大部分都差不多 .

像程式工程師一樣思考

寫程式中最困難的事情之一,不是您需要學習的語法,而是如何應用它來解決現實世界中的問題。 您需要開始像個程式設計師一樣思考 — 這通常與檢視程式目標的說明有關,並確定實現這些功能所需的程式碼,以及如何使它們協同工作。

這需要辛勤工作,程式語法經驗和練習 — 以及一點創造力。 你寫了越多程式碼,你就會越熟練。 我們不能保證你會在5分鐘內開發出“程式設計師的大腦”,但我們會給你很多機會在整個課程中練習"像程式設計師一樣思考"。

考慮到這一點,讓我們看一下我們將在本文中構建的範例,並審視將其分解為具體任務的大致流程。

範例 — 猜數字遊戲

在本文中,我們將向您展示如何構建您可以在下面看到的簡單遊戲:

好好玩一下游戲再繼續吧 —— 在繼續前先與這個遊戲熟悉起來。

讓我們假設你的老闆給了你以下關於創建這個遊戲的簡介:

我要你幫我做一個很簡單的猜數字遊戲 .
玩家要在 10 回合內猜中一個1到100之間的隨機數字 ,
每回合結束時都要告訴玩家他們猜對還是猜錯 ,
然後要是他們猜錯 , 要告訴他們數字猜的太小還是太大 ,
這個遊戲會在玩家猜對 , 或是猜超過 10 次時結束 ,
且遊戲結束時 , 要提供一個選項讓玩家可以再玩一次 .

當看到上面的介紹後,我們可以做的第一件事就是開始拆解,盡可能的像個程式設計師,將它拆解為簡單可執行的任務:

  1. 產生一個1到100間的隨機數字。
  2. 從一開始,紀錄玩家目前回合數。
  3. 提供玩家猜數字的方向(太大還是太小)。
  4. 當玩家送出第一個猜測後,將猜測記錄下來,讓玩家可以看到他們之前的猜測。
  5. 接著檢查數字是否猜中。
  6. 如果數字猜對:
    1. 顯示恭喜訊息。
    2. 使玩家不能再輸入更多猜測(避免把遊戲玩壞)。
    3. 顯示控制鈕讓玩家可以重新開始遊戲。
  7. 如果數字猜錯而且玩家有剩餘回合數:
    1. 告訴玩家他猜錯了。
    2. 讓玩家輸入其他的猜測
    3. 回合數增加1。
  8. 如果數字猜錯而且玩家沒有剩餘回合數:
    1. 告訴玩家遊戲結束。
    2. 使玩家不能再輸入更多猜測(避免把遊戲玩壞)。
    3. 顯示控制鈕讓玩家可以重新開始遊戲。
  9. 當遊戲重新開始,確保遊戲邏輯和畫面(UI,使用這介面)全面重設,然後回到第一步。

現在,讓我們繼續向前,一路上我們檢視如何將這些步驟轉化為程式碼、建構出上面的範例與探索JavaScript的功能。

初步設定

在課程開始前,我們希望你可以複製一份number-guessing-game-start.html到自己的電腦中(see it live here)。用瀏覽器與文字編輯器將當按打開時,你會看到簡單的標題、說明段落還有輸入猜測的表格,然而表格目前還不會做任何事情。

所有的程式碼都會加入放在HTML底部的<script>元素裡:

<script>

  // Your JavaScript goes here

</script>

加入變數儲存我們的資料

我們一起開始吧。首先,在你的<script> 元素裡加入以下幾行:

let randomNumber = Math.floor(Math.random() * 100) + 1;

const guesses = document.querySelector('.guesses');
const lastResult = document.querySelector('.lastResult');
const lowOrHi = document.querySelector('.lowOrHi');

const guessSubmit = document.querySelector('.guessSubmit');
const guessField = document.querySelector('.guessField');

let guessCount = 1;
let resetButton;

這一區塊的程式碼設定我們的程式中用來儲存資料的變數。簡單的來說,「變數」是「值」的容器(值可以是數字、一串文字或是其他東西)。你可以用「關鍵字」(keyword) let(或是var)後面加上變數的名字來建立變數(在之後的文章你會看到兩者的差別)。利用關鍵字 const 建立常數,常數(Constant)是用來儲存你不會更改的值。我們用常數儲存使用者介面的參照,使用者介面中的文字可能會改變,但是參照所指的HTML元素的不會改變。

藉由等於符號(=)後面加上一個值,你可以指定變數或是常數的值。

在我們的範例中:

  • 第一個變數 — randomNumber — 被指定成一個由數學運算的1到100間的隨機數字
  • 接著的三個常數,分別儲存HTML中結果段落的參照,在後面的程式碼中,參照被用來插入一些數值:
    <p class="guesses"></p>
    <p class="lastResult"></p>
    <p class="lowOrHi"></p>
  • 接著的兩個常數,分別儲存表格中的文字輸入和送出按鈕,之後用來控制送出猜測的數字。
    <label for="guessField">Enter a guess: </label><input type="text" id="guessField" class="guessField">
    <input type="submit" value="Submit guess" class="guessSubmit">
  • 後兩個變數,一個儲存回合數1,另一個儲存指向重新開始按鈕的參照(按鈕之後會存在)。

Note: 從下一篇文章開始,在之後的課程會學到更多變數。

函式

下一步,將下面這段添加到之前寫的那段程式碼:

function checkGuess() {
  alert('I am a placeholder');
}

函式是一段可重複利用的程式碼塊。建立一個函式便可以反覆運行並避免重複撰寫程式碼。定義函式有很多方法,在此我們先專注在一種簡單的方式。這裏我們以關鍵字 function 、自訂函式名、一對括號以及一對花括號({ })建立函式。花括號中的程式碼便是我們調用函式時所要實際執行的程式碼。

輸入函式名稱與括號便可以執行函式。

試著儲存的的程式碼並重新整理瀏覽器畫面。

進入 開發者工具 JavaScript console, 並輸入下面這行:

checkGuess();

 當按下 Return/Enter 時,你會看到一個警告跳窗顯示「I am a placeholder」。我們已經在程式中定義好一個函式,只要我們調用這個函式,函式便會建立一個警告跳窗。

Note: 你會在後續的課程中學習到更多關於函式。

運算子

JavaScript 運算子可以讓我們執行比較、數學運算、連接字符串等。

儲存我們的程式碼並刷新頁面,開啟 開發者工具 JavaScript console 。如果你不能打開以上的工具,你可以嘗試手動輸入以下的範例——在每個欄位分別輸入同樣的内容,再分別按下Return/Enter, 然後你就可以看到返回的結果。如果你不能快速打開瀏覽器開發工具, 你可以使用内嵌的應用程式中輸入以下範例:

首先讓我們看一下以下的算數運算子:

Operator Name Example
+ Addition 6 + 9
- Subtraction 20 - 15
* Multiplication 3 * 7
/ Division 10 / 5

你也可以使用 + 來連接字串 (也稱爲編程中的連接)。可嘗試輸入以下幾行程式,每次一行:

var name = 'Bingo';
name;
var hello = ' says hello!';
hello;
var greeting = name + hello;
greeting;

也可以使用一些運算捷徑, 被稱爲增量賦值運算子。舉例,如果你只是簡單想將兩個字串加在一起,你可以這樣做:

name += ' says hello!';

相當於

name = name + ' says hello!';

當我們進行true/false測試時 (舉例:以下條件 — below), 我們可以使用比較運算子,如:

Operator Name Example
=== Strict equality (is it exactly the same?) 5 === 2 + 4
!== Non-equality (is it not the same?) 'Chris' !== 'Ch' + 'ris'
< Less than 10 < 6
> Greater than 10 > 20

Conditionals

回到 checkGuess() 函數,我們希望的結果當然不只是跳出placeholder的訊息而已。 我們更想要知道這個函數將如何檢查玩家的猜測是否準確,並返回正確的結果。

所以可以將現在的 checkGuess() 函數替換爲以下版本:

function checkGuess() {
  var userGuess = Number(guessField.value);
  if (guessCount === 1) {
    guesses.textContent = 'Previous guesses: ';
  }
  guesses.textContent += userGuess + ' ';
 
  if (userGuess === randomNumber) {
    lastResult.textContent = 'Congratulations! You got it right!';
    lastResult.style.backgroundColor = 'green';
    lowOrHi.textContent = '';
    setGameOver();
  } else if (guessCount === 10) {
    lastResult.textContent = '!!!GAME OVER!!!';
    setGameOver();
  } else {
    lastResult.textContent = 'Wrong!';
    lastResult.style.backgroundColor = 'red';
    if(userGuess < randomNumber) {
      lowOrHi.textContent = 'Last guess was too low!';
    } else if(userGuess > randomNumber) {
      lowOrHi.textContent = 'Last guess was too high!';
    }
  }
 
  guessCount++;
  guessField.value = '';
  guessField.focus();
}

突然出現了很多程式!讓我們完整地看一遍這些程式並介紹它們是如何運行的。

  • 第一行(上面的第2行)聲明一個名為的變量userGuess,並將其值設置為在文本字段內輸入的當前值。我們還通過內置Number()方法運行此值,以確保該值絕對是一個數字。
  • 接下來,我們遇到第一個條件代碼塊(上面的第3-5行)。條件代碼塊允許您有選擇地運行代碼,具體取決於某個條件是否為真。它看起來有點像功能,但事實並非如此。最簡單的條件塊形式從關鍵字開始if,然後是一些括號,然後是一些花括號。在括號內,我們包括一個測試。如果測試返回true,我們在花括號內運行代碼。如果沒有,我們不會,繼續下一段代碼。在這種情況下,測試是測試guessCount變量是否等於1(即這是否是玩家的第一次去):
    guessCount === 1
    如果是,我們將猜測段落的文本內容等於“上一個猜測:”。如果沒有,我們不會。
  • 第6行將當前userGuess值附加到guesses段落的末尾,加上一個空格,以便在顯示的每個猜測之間有一個空格。
  • 下一個區塊(上面第8-24行)做了一些檢查:
    • 第一個if(){ }檢查用戶的猜測是否等於randomNumberJavaScript頂部的設置。如果是,玩家已經猜對了,遊戲就贏了,所以我們向玩家展示一個漂亮綠色的祝賀消息,清除低/高猜測信息框的內容,並運行一個叫做的函數setGameOver(),我們'我稍後再討論。
    • 現在我們使用else if(){ }結構將另一個測試鏈接到最後一個測試的末尾。這個檢查此轉彎是否是用戶的最後一個轉彎。如果是,則程序執行與上一個程序段相同的操作,除了遊戲結束消息而不是祝賀消息。
    • 鏈接到此代碼末尾的最後一個塊(else { }包含)僅在其他兩個測試都沒有返回true時運行的代碼(即,玩家沒有猜對,但他們還有更多的猜測)。在這種情況下,我們告訴他們他們錯了,然後我們執行另一個條件測試以檢查猜測是高於還是低於答案,顯示適當的進一步消息以告訴他們更高或更低。
  • 函數中的最後三行(上面的第26-28行)讓我們準備好提交下一個猜測。我們將1添加到guessCount變量中,以便玩家輪流使用它(++是遞增操作 - 遞增1),並將值從表單文本字段中清空並再次聚焦,準備好輸入下一個猜測。

事件

在這一點上,我們有一個很好的實現checkGuess()函數,但它不會做任何事情,因為我們還沒有調用它。理想情況下,我們想在按下“提交猜測”按鈕時調用它,為此,我們需要使用一個事件。事件是在瀏覽器中發生的操作,例如單擊按鈕,頁面加載或視頻播放,以響應我們可以運行代碼塊。偵聽事件發生的構造稱為事件偵聽器,響應事件觸發而運行的代碼塊稱為事件處理程序

checkGuess()函數下面添加以下行:

guessSubmit.addEventListener('click', checkGuess);

這裡我們為guessSubmit按鈕添加一個事件監聽器。這是一個方法,它接受兩個輸入值(稱為參數) - 我們正在監聽的事件類型(在本例中click)作為字符串,以及我們想要在事件發生時運行的代碼(在這種情況下是checkGuess()函數 -請注意,在內部編寫時我們不需要指定括號addEventListener()

現在嘗試保存並刷新代碼,現在您的示例應該可以正常工作。現在唯一的問題是,如果你猜對了正確的答案或用完了猜測,那麼遊戲就會破裂,因為我們還沒有定義setGameOver()遊戲結束後應該運行的功能。讓我們現在添加我們缺少的代碼並完成示例功能。

完成遊戲功能

讓我們加入 setGameOver() 這個函式到我們程式碼的底部並演練它。 Add this now, below the rest of your JavaScript:

function setGameOver() {
  guessField.disabled = true;
  guessSubmit.disabled = true;
  resetButton = document.createElement('button');
  resetButton.textContent = 'Start new game';
  document.body.appendChild(resetButton);
  resetButton.addEventListener('click', resetGame);
}
  • The first two lines disable the form text input and button by setting their disabled properties to true. This is necessary, because if we didn't, the user could submit more guesses after the game is over, which would mess things up.
  • The next three lines generate a new <button> element, set its text label to "Start new game", and add it to the bottom of our existing HTML.
  • The final line sets an event listener on our new button so that when it is clicked, a function called resetGame() is run.

Now we need to define this function too! Add the following code, again to the bottom of your JavaScript:

function resetGame() {
  guessCount = 1;

  var resetParas = document.querySelectorAll('.resultParas p');
  for (var i = 0 ; i < resetParas.length ; i++) {
    resetParas[i].textContent = '';
  }

  resetButton.parentNode.removeChild(resetButton);

  guessField.disabled = false;
  guessSubmit.disabled = false;
  guessField.value = '';
  guessField.focus();

  lastResult.style.backgroundColor = 'white';

  randomNumber = Math.floor(Math.random() * 100) + 1;
}

This rather long block of code completely resets everything to how it was at the start of the game, so the player can have another go. It:

  • Puts the guessCount back down to 1.
  • Clears all the information paragraphs.
  • Removes the reset button from our code.
  • Enables the form elements, and empties and focuses the text field, ready for a new guess to be entered.
  • Removes the background color from the lastResult paragraph.
  • Generates a new random number so that you are not just guessing the same number again!

At this point you should have a fully working (simple) game — congratulations!

All we have left to do now in this article is talk about a few other important code features that you've already seen, although you may have not realized this.

迴圈

One part of the above code that we need to take a more detailed look at is the for loop. Loops are a very important concept in programming, which allow you to keep running a piece of code over and over again, until a certain condition is met.

To start with, go to your browser developer tools JavaScript console again, and enter the following:

for (var i = 1 ; i < 21 ; i++) { console.log(i) }

What happened? The numbers 1 to 20 were printed out in your console. This is because of the loop. A for loop takes three input values (arguments):

  1. A starting value: In this case we are starting a count at 1, but this could be any number you like. You can replace i with any name you like too, but i is used as a convention because it's short and easy to remember.
  2. An exit condition: Here we have specified i < 21 — the loop will keep going until i is no longer less than 21. When i reaches 21, the loop will no longer run.
  3. An incrementor: We have specified i++, which means "add 1 to i". The loop will run once for every value of i, until i reaches a value of 21 (as discussed above). In this case, we are simply printing the value of i out to the console on every iteration using console.log().

Now let's look at the loop in our number guessing game — the following can be found inside the resetGame() function:

var resetParas = document.querySelectorAll('.resultParas p');
for (var i = 0 ; i < resetParas.length ; i++) {
  resetParas[i].textContent = '';
}

This code creates a variable containing a list of all the paragraphs inside <div class="resultParas"> using the querySelectorAll() method, then it loops through each one, removing the text content of each.

A small discussion on objects

Let's add one more final improvement before we get to this discussion. Add the following line just below the var resetButton; line near the top of your JavaScript, then save your file:

guessField.focus();

This line uses the focus() method to automatically put the text cursor into the <input> text field as soon as the page loads, meaning that the user can start typing their first guess right away, and doesn't have to click the form field first. It's only a small addition, but it improves usability — giving the user a good visual clue as to what they've got to do to play the game.

Let's analyze what's going on here in a bit more detail. In JavaScript, everything is an object. An object is a collection of related functionality stored in a single grouping. You can create your own objects, but that is quite advanced and we won't be covering it until much later in the course. For now, we'll just briefly discuss the built-in objects that your browser contains, which allow you to do lots of useful things.

In this particular case, we first created a guessField variable that stores a reference to the text input form field in our HTML — the following line can be found amongst our variable declarations near the top:

var guessField = document.querySelector('.guessField');

To get this reference, we used the querySelector() method of the document object. querySelector() takes one piece of information — a CSS selector that selects the element you want a reference to.

Because guessField now contains a reference to an <input> element, it will now have access to a number of properties (basically variables stored inside objects, some of which can't have their values changed) and methods (basically functions stored inside objects). One method available to input elements is focus(), so we can now use this line to focus the text input:

guessField.focus();

Variables that don't contain references to form elements won't have focus() available to them. For example, the guesses variable contains a reference to a <p> element, and guessCount contains a number.

Playing with browser objects

Let's play with some browser objects a bit.

  1. First of all open your program up in a browser.
  2. Next, open your browser developer tools, and make sure the JavaScript console tab is open.
  3. Type in guessField and the console will show you that the variable contains an <input> element. You'll also notice that the console autocompletes object names that exist inside the execution environment, including your variables!
  4. Now type in the following:
    guessField.value = 'Hello';
    The value property represents the current value entered into the text field. You'll see that by entering this command, we've changed what that is!
  5. Now try typing in guesses and pressing return. The console will show you that the variable contains a <p> element.
  6. Now try entering the following line:
    guesses.value
    The browser will return undefined, because value doesn't exist on paragraphs.
  7. To change the text inside a paragraph, you need the textContent property instead. Try this:
    guesses.textContent = 'Where is my paragraph?';
  8. Now for some fun stuff. Try entering the below lines, one by one:
    guesses.style.backgroundColor = 'yellow';
    guesses.style.fontSize = '200%';
    guesses.style.padding = '10px';
    guesses.style.boxShadow = '3px 3px 6px black';
    Every element on a page has a style property, which itself contains an object whose properties contain all the inline CSS styles applied to that element. This allows us to dynamically set new CSS styles on elements using JavaScript.

Finished for now...

So that's it for building the example — you got to the end, well done! Try your final code out, or play with our finished version here. If you can't get the example to work, check it against the source code.

In this module