構建自己的函式

在上一篇文章中處理了大部分必要的理論知識後,本文將提供實踐經驗。在這裡,你將獲得一些構建自己的自定義函式的實踐。在此過程中,我們還將解釋一些處理函式的有用細節。

先決條件 對 HTML、CSS 和 JavaScript 初步知識 的基本瞭解。此外,還需要了解 函式——可重用的程式碼塊
目標 提供一些構建自定義函式的實踐,並解釋一些更有用的相關細節。

主動學習:讓我們構建一個函式

我們將要構建的自定義函式將被稱為 displayMessage()。它將在網頁上顯示一個自定義的訊息框,並將充當瀏覽器內建的 alert() 函式的自定義替代品。我們之前見過這個函式,但讓我們回顧一下。在你喜歡的任何頁面上,在瀏覽器的 JavaScript 控制檯中鍵入以下內容:

js
alert("This is a message");

alert 函式接受一個引數——在警報框中顯示的字串。嘗試更改字串以更改訊息。

alert 函式的功能有限:你可以更改訊息,但不能輕鬆地更改其他任何內容,例如顏色、圖示或其他任何內容。我們將構建一個更有趣的函式。

注意:此示例應該在所有現代瀏覽器中都能正常工作,但在稍舊的瀏覽器中,樣式可能看起來有點奇怪。我們建議你在現代瀏覽器(如 Firefox、Opera 或 Chrome)中進行此練習。

基本函式

首先,讓我們構建一個基本的函式。

注意:對於函式命名約定,應遵循與 變數命名約定 相同的規則。這很好,因為你可以區分它們——函式名後面帶有括號,而變數沒有。

  1. 首先訪問 function-start.html 檔案並製作一個本地副本。你會看到 HTML 非常簡單——主體只包含一個按鈕。我們還提供了一些基本的 CSS 來設定自定義訊息框的樣式,以及一個空的 <script> 元素來放置我們的 JavaScript 程式碼。
  2. 接下來,在 <script> 元素內新增以下內容:
    js
    function displayMessage() {
      ...
    }
    
    我們從關鍵字 function 開始,這意味著我們正在定義一個函式。後面跟著我們想要賦予函式的名稱、一對括號和一對花括號。我們想要賦予函式的任何引數都放在括號內,當我們呼叫函式時執行的程式碼放在花括號內。
  3. 最後,在花括號內新增以下程式碼:
    js
    const body = document.body;
    
    const panel = document.createElement("div");
    panel.setAttribute("class", "msgBox");
    body.appendChild(panel);
    
    const msg = document.createElement("p");
    msg.textContent = "This is a message box";
    panel.appendChild(msg);
    
    const closeBtn = document.createElement("button");
    closeBtn.textContent = "x";
    panel.appendChild(closeBtn);
    
    closeBtn.addEventListener("click", () =>
      panel.parentNode.removeChild(panel),
    );
    

這段程式碼相當長,所以我們將逐步為你講解。

第一行使用 DOM API 獲取全域性 document 物件的 body 屬性,並將其賦值給一個名為 body 的常量,以便我們稍後對其進行操作。

js
const body = document.body;

下一部分使用一個名為 document.createElement() 的 DOM API 函式建立一個 <div> 元素,並將對它的引用儲存在一個名為 panel 的常量中。此元素將成為訊息框的外層容器。

然後,我們使用另一個名為 Element.setAttribute() 的 DOM API 函式為我們的面板設定一個 class 屬性,其值為 msgBox。這樣做是為了更容易地設定元素的樣式——如果你檢視頁面上的 CSS,你會看到我們正在使用 .msgBox 類選擇器來設定訊息框及其內容的樣式。

最後,我們對之前儲存的 body 常量呼叫一個名為 Node.appendChild() 的 DOM 函式,它將一個元素巢狀在另一個元素內作為其子元素。我們將面板 <div> 指定為我們想要附加到 <body> 元素內的子元素。我們需要這樣做,因為我們建立的元素不會自己出現在頁面上——我們需要指定放置它的位置。

js
const panel = document.createElement("div");
panel.setAttribute("class", "msgBox");
body.appendChild(panel);

接下來的兩部分使用了我們已經見過的相同的 createElement()appendChild() 函式來建立兩個新元素——一個 <p> 和一個 <button>——並將它們作為面板 <div> 的子元素插入頁面中。我們使用它們的 Node.textContent 屬性(表示元素的文字內容)在段落中插入一條訊息,並在按鈕中插入一個“x”。當用戶想要關閉訊息框時,此按鈕將是需要點選/啟用的按鈕。

js
const msg = document.createElement("p");
msg.textContent = "This is a message box";
panel.appendChild(msg);

const closeBtn = document.createElement("button");
closeBtn.textContent = "x";
panel.appendChild(closeBtn);

最後,我們呼叫 addEventListener() 來新增一個函式,該函式將在使用者點選“關閉”按鈕時呼叫。該程式碼將從頁面中刪除整個面板——以關閉訊息框。

簡單來說,addEventListener() 方法由按鈕(實際上,頁面上的任何元素)提供,可以傳遞一個函式和一個事件的名稱。在本例中,事件的名稱為“click”,這意味著當用戶點選按鈕時,函式將執行。你將在我們的 事件文章 中瞭解更多關於事件的資訊。函式內的行使用 Node.removeChild() DOM API 函式指定我們想要刪除 HTML 元素的特定子元素——在本例中,是面板 <div>

js
closeBtn.addEventListener("click", () => panel.parentNode.removeChild(panel));

基本上,這段程式碼生成的 HTML 程式碼塊如下所示,並將其插入頁面中:

html
<div class="msgBox">
  <p>This is a message box</p>
  <button>x</button>
</div>

有很多程式碼需要處理——如果現在不記得每個部分是如何工作的,請不要太擔心!我們這裡要重點關注的是函式的結構和用法,但我們想為此示例展示一些有趣的內容。

呼叫函式

你現在已將函式定義正確地寫入 <script> 元素中,但它本身不會執行任何操作。

  1. 嘗試在你的函式下面包含以下行來呼叫它:
    js
    displayMessage();
    
    此行呼叫函式,使其立即執行。當你儲存程式碼並在瀏覽器中重新載入它時,你會看到一個小訊息框立即出現,並且只出現一次。畢竟,我們只調用它一次。
  2. 現在在示例頁面上開啟瀏覽器開發者工具,轉到 JavaScript 控制檯並再次在那裡鍵入該行,你會看到它再次出現!所以這很有趣——我們現在有一個可重用的函式,可以隨時呼叫。但我們可能希望它響應使用者和系統操作而出現。在一個真實的應用程式中,這樣的訊息框可能會在新的資料可用、發生錯誤、使用者嘗試刪除他們的個人資料(“你確定要這樣做嗎?”)或使用者新增新的聯絡人並且操作成功完成等情況下被呼叫。在本演示中,我們將使訊息框在使用者點選按鈕時出現。
  3. 刪除你之前新增的行。
  4. 接下來,我們將選擇按鈕並將對它的引用儲存在一個常量中。將以下行新增到你的程式碼中,位於函式定義之上:
    js
    const btn = document.querySelector("button");
    
  5. 最後,在上一行下面新增以下行:
    js
    btn.addEventListener("click", displayMessage);
    
    與我們的 closeBtn 的點選事件處理程式類似,這裡我們正在響應按鈕被點選而呼叫一些程式碼。但在此例中,我們不是呼叫包含某些程式碼的匿名函式,而是按名稱呼叫我們的 displayMessage() 函式。
  6. 嘗試儲存並重新整理頁面——現在你應該會看到當你點選按鈕時訊息框出現。

你可能想知道為什麼我們沒有在函式名後面包含括號。這是因為我們不想立即呼叫函式——只有在按鈕被點選後才會呼叫。如果你嘗試將該行更改為:

js
btn.addEventListener("click", displayMessage());

並儲存和重新載入,你會看到訊息框在沒有點選按鈕的情況下出現!在這種情況下,括號有時被稱為“函式呼叫運算子”。只有當你希望在當前作用域中立即執行函式時才使用它們。同樣,匿名函式內部的程式碼不會立即執行,因為它位於函式作用域內。

如果你嘗試了最後一個實驗,請確保在繼續之前撤消最後的更改。

使用引數改進函式

就目前而言,該函式仍然不是很有用——我們不希望每次都顯示相同的預設訊息。讓我們透過新增一些引數來改進我們的函式,以便我們可以使用一些不同的選項來呼叫它。

  1. 首先,更新函式的第一行:
    js
    function displayMessage() {
    
    更改為:
    js
    function displayMessage(msgText, msgType) {
    
    現在,當我們呼叫函式時,可以在括號內提供兩個變數值來指定要在訊息框中顯示的訊息以及訊息的型別。
  2. 為了使用第一個引數,更新函式內的以下行:
    js
    msg.textContent = "This is a message box";
    
    更改為:
    js
    msg.textContent = msgText;
    
  3. 最後,你現在需要更新函式呼叫以包含一些更新的訊息文字。更改以下行:
    js
    btn.addEventListener("click", displayMessage);
    
    更改為以下程式碼塊:
    js
    btn.addEventListener("click", () =>
      displayMessage("Woo, this is a different message!"),
    );
    
    如果我們想要為呼叫的函式在括號內指定引數,那麼我們不能直接呼叫它——我們需要將其放在匿名函式內,以便它不在立即作用域內,因此不會立即被呼叫。現在它只有在按鈕被點選後才會被呼叫。
  4. 重新載入並再次嘗試程式碼,你會看到它仍然可以正常工作,只是現在你還可以更改引數內的訊息以在框中顯示不同的訊息!

更復雜的引數

接下來是下一個引數。這將涉及更多工作——我們將設定它,以便根據 msgType 引數設定為的值,函式將顯示不同的圖示和不同的背景顏色。

  1. 首先,從 GitHub 下載此練習所需的圖示(警告聊天)。將它們儲存到一個名為 icons 的新資料夾中,該資料夾與你的 HTML 檔案位於同一位置。

    注意:警告和聊天圖示最初是在 iconfinder.com 上找到的,由 Nazarrudin Ansyari 設計——謝謝!(實際的圖示頁面已被移動或刪除。)

  2. 接下來,找到 HTML 檔案中的 CSS。我們將進行一些更改以騰出空間放置圖示。首先,將 .msgBox 的寬度從:
    css
    width: 200px;
    
    更改為:
    css
    width: 242px;
    
  3. 接下來,在 .msgBox p { } 規則內新增以下行:
    css
    padding-left: 82px;
    background-position: 25px center;
    background-repeat: no-repeat;
    
  4. 現在我們需要在 displayMessage() 函式中新增程式碼來處理圖示的顯示。在函式的結束花括號 (}) 正上方新增以下程式碼塊:

    js
    if (msgType === "warning") {
      msg.style.backgroundImage = "url(icons/warning.png)";
      panel.style.backgroundColor = "red";
    } else if (msgType === "chat") {
      msg.style.backgroundImage = "url(icons/chat.png)";
      panel.style.backgroundColor = "aqua";
    } else {
      msg.style.paddingLeft = "20px";
    }
    
    這裡,如果將msgType引數設定為'warning',則會顯示警告圖示,並將面板的背景顏色設定為紅色。如果將其設定為'chat',則會顯示聊天圖示,並將面板的背景顏色設定為青綠色。如果根本沒有設定msgType引數(或設定為其他值),則程式碼的else { }部分開始執行,段落將使用預設填充且沒有圖示,並且也沒有設定背景面板顏色。如果沒有提供msgType引數,這將提供一個預設狀態,這意味著它是一個可選引數!
  5. 讓我們測試一下更新後的函式,嘗試將displayMessage()呼叫從以下內容
    js
    displayMessage("Woo, this is a different message!");
    
    更新為以下內容之一
    js
    displayMessage("Your inbox is almost full — delete some mails", "warning");
    displayMessage("Brian: Hi there, how are you today?", "chat");
    
    您可以看到我們(現在不再那麼)小的函式變得多麼有用。

注意:如果您在嘗試使示例工作時遇到問題,請隨時將您的程式碼與GitHub 上的完成版本 (檢視其執行效果) 進行比較,或向我們尋求幫助。

測試你的技能!

您已閱讀完本文,但您能記住最重要的資訊嗎?在繼續之前,您可以找到一些進一步的測試來驗證您是否保留了這些資訊——請參閱測試您的技能:函式。這些測試需要下一篇文章中介紹的技能,因此您可能需要先閱讀下一篇文章,然後再嘗試測試。

結論

恭喜您閱讀到最後!本文帶您完成了構建實用自定義函式的整個過程,只需稍加修改,就可以將其移植到實際專案中。在下一篇文章中,我們將透過解釋另一個相關的基本概念——返回值——來總結函式。