MDN wants to learn about developers like you: https://qsurvey.mozilla.com/s3/MDN-Learn-Section-Survey

正在翻譯中。

歡迎來到 MDN 的 JavaScript 初學者課程!在這第一個章節中,我們將綜觀 JavaScript ,思考一些問題像是"這是什麼?"和"它的功能是什麼?",確保你了解 JavaScript 的功用。

準備條件: 有基本的計算機讀寫能力,基本了解 HTML 和 CSS。
目標: 為了熟悉 JavaScript 是什麼,它可以做什麼,以及它如何適用於網路站點。

高級定義

JavaScript是一種准許您在網頁上實現複雜事物的程式語言 — 每次網頁都比固定在那裡展現靜態資訊給你看做得要多 — 及時顯示內容更新、交互式地圖、繪製2D/3D 動畫圖形以及滾動視訊點唱機等等。— 你會發現 JavaScript 幾乎無處不在。它是標準網路技術的第三層,另外兩個(HTML 和 CSS)我們在學習其他領域的部分已經詳細涵蓋了。

  • HTML 是一種標記語言,我們使用它構建和給我們的內容賦予意義, 例如定義段落,標題,數據表格以及在頁面嵌入圖片和視頻等等。.
  • CSS 是一種樣式規則的語言,用於在我們的 HTML 內容上應用樣式,例如設置背景顏色、字體以及讓內容多列呈現等等。
  • JavaScript 是一種程式語言,它使你能夠創建動態更新內容、控制多媒體,動畫圖片等等幾乎所有事。(好吧,不是所有,但這是非常神奇的僅通過短短幾行 JavaScript 程式碼就可以實現的東西。)

這三層很好的構建在一起。讓我們以一個簡單的文本為例。我們可以使用 HTML 標記來呈現它的結構和意圖:

<p>Player 1: Chris</p>

然後我們可以添加一些樣式混合到一起,獲取更好看的外觀:

p {
  font-family: 'helvetica neue', helvetica, sans-serif;
  letter-spacing: 1px;
  text-transform: uppercase;
  text-align: center;
  border: 2px solid rgba(0,0,200,0.6);
  background: rgba(0,0,200,0.3);
  color: rgba(0,0,200,0.6);
  box-shadow: 1px 1px 2px rgba(0,0,200,0.4);
  border-radius: 10px;
  padding: 3px 10px;
  display: inline-block;
  cursor:pointer;
}

最後,我們可以添加一些  JavaScript 來實現動態行為:

var para = document.querySelector('p');

para.addEventListener('click', updateName);

function updateName() {
  var name = prompt('Enter a new name');
  para.textContent = 'Player 1: ' + name;
}

試試點擊文本看看會發生什麼(注意你同樣可以在 GitHub 找到這個 demo — 查看源程式碼 source code 或 run it live)!

JavaScript 可以做比這些多得多 — 讓我們來更詳細的探索一下。

那麼它究竟可以做什麼呢?

JavaScript 語言的核心包含了很多常用的程式功能供你使用,如:

  • 在變數內部存儲有用的值。如上面的例子,我們請求輸入一個新的名字並存儲,那個變數就叫做name.
  • 對文本片段做操作(在程式裡稱作"strings")。在上面的例子裡我們拿了字串 "Player 1: " 並且拼串 name 變數來創建一個完整文本標籤,如:''Player 1: Chris"。
  • 執行程式碼響應到確切的事件發生在網頁上。我們在上述例子使用 click 事件偵查,當按鈕被點擊時返回執行更新文本標籤的程式碼。 
  • 以及其他更多功能!

在JavaScript語言的內核之上還有更多令人激動的功能。也被稱作 應用程式接口(APIs) 它為你使用  JavaScript 程式碼提供了額外強大的支持。

APIs 是以程式碼預先製作完成的模組,其支援開發者實現較難或無法實現的程式。 他們在編寫程式方面與預先為了建造首頁而製作好的套件做相同的事情 — 拿預先裁切好的板子與螺絲並把他們組合成書架比自己設計、找到合適的木材、裁切成正確的形狀和尺寸、找到合適的螺絲並把他們組合成書架更簡單。

他們通常分為兩類。

Browser APIs( 瀏覽器APIs ) 是被安裝在你的網頁瀏覽器內且可以由本地端的環境中輸出資料或實現複雜的功能。

舉例而言:

  • DOM (文件物件模組) API 使你可以操作HTML和CSS,創造、移除和更動 HTML,以新的風格動態的支援你的頁面,等等。每次你看見彈出式視窗展現在網頁上、或一些新的內文展現範例(如同我們曾經在我們簡單的展示中見過的),那就是DOM在做的事。
  • Geolocations(地理位置) API 可以讓你取得目前的位置資訊. 這也是 Google Maps 如何取得你的位置並把你的位置標示在地圖上。
  • Canvas 及 WebGL APIs 可以讓你在網頁上創造 2D 及 3D 圖像。人們正大量的使用這項技術來創造有趣的產品 — 參見 Chrome Experiments 及 webglsamples.
  • Audio and Video APIs ,其中的HTMLMediaElement 及 WebRTC 可以讓你藉由各種媒體做有趣的事。例如在網頁中播放音樂或影片,又或是使用你的網路攝影機將你的影像在另一個人的網頁上撥放。(可以試著從這個範例 Snapshot demo 了解基本的概念).

Note: 上面列出的範例大多無法在舊版本的瀏覽器上運作 — 當你在嘗試範例時,最好使用 Firefox, Chrome, Edge 或 Opera 來查看運作結果。另外,當你想實際上線你的網頁時(也就是會有其他人會使用時),就需要考量 跨瀏覽器支援(cross browser testing) 。

第三方 APIs 不是來自瀏覽器原始創建,但你可以在網路上抓取他們的程式碼和信息。例如:

  • Twitter API 能讓你做很多事,像是顯示最新的Twitter貼文在你的網站上。
  • Google Maps API 能讓你在自己的網站中嵌入訂製的地圖與其他相關功能。

Note: 我們不會在此涵蓋這些進階的APIs。你可以得到更多資訊在我們的 Client-side web APIs module

這裡的內容豐富,但是目前不要興奮過頭,你不會因為學了JavaScript 24小時就能建立下一個Facebook,、Google Map或Instagram。這裡主要包含許多基礎內容,我想這也是你在這裡的原因,讓我們接著繼續吧!

JavaScript 在你的頁面做了些什麼?

在這裡,我們將開始實際查看一些程式碼,並且在你的頁面上跑一些 JavaScript 程式碼的時候,探索探索實際發生了什麼。

讓我們簡要概括一下在瀏覽器上載入一個網頁時發生了怎樣的情況(首先在我們的 Css如何工作 這篇文章中有談論到)。當瀏覽器在載入一個網頁,就是在執行環境(瀏覽器選項卡)內部運行程式碼(HTML,CSS 和 Javascript)。這就像是 工廠採集一些原材料(程式中的code) 並且輸出成產品(看到的網頁)。

JavaScript由瀏覽器的JavaScript引擎執行,在HTML與CSS會組織完成放在放在網頁之中之後。如此確保網頁的結構與樣式在JavaScript開始運行時已經全部到位。

這是件好事,因為JavaScript透過Document Object Model(等等會介紹)動態修改HTML與CSS來更新使用者介面。如果JavaScript載入後試著在HTML與CSS生效之前執行,就會可能產生錯誤。

瀏覽器安全性

每個分頁都有它自己的程式碼執行環境(bucket,技術用語為"excution environments"),這意味著在絕大部分的情形之下,分頁裡程式碼會完全分離運行,分頁裡程式碼無法直接影響其他分頁的程式碼,或是影響另一個網站。若非如此小偷將可以寫程式竊取網站的資料,或是做其他壞事,所以這是一個好的安全措施。

Note: 是存在一些安全的方法可以讓網頁或分頁間傳遞指令與資料,不過這些進階的技術不會在涵蓋在這個課程之中。

JavaScript 運行指令

當瀏覽器遇到JavaScript區塊,通常從上到下順序執行,因此你需要注意安排JavaScript區塊的順序。為了舉例,讓我們一起倒回去第一個範例:

var para = document.querySelector('p');

para.addEventListener('click', updateName);

function updateName() {
  var name = prompt('Enter a new name');
  para.textContent = 'Player 1: ' + name;
}

在這之中我們選擇text paragraph(段落,HTML中的一種標記,第一行),並把事件收聽器附接上它,所以當它被點擊時updateName()程式區塊會被執行。updateName()程式區塊(此類可以被再利用的程式區塊被稱作'函數', function)會詢問使用者一個新名字,然後將新名字插入段落之中更新顯示內容。

如果你交換前兩行的程式碼,程式不再會正常運作。相反的會在瀏覽器開發者主控台中回傳一個錯誤訊息 — TypeError: para is undefined,意思是para物件目前不存在,所以我們不能將一個事件收聽器接上去。

Note: 這是一個很常見的錯誤 — 你需要注意在程式碼中參照的物件,它必須先存在才能進行各式各樣的操作。

解釋與編譯的程式碼

你可能在程式相關的文章中看過編譯式直譯式這兩個詞。JavaScript是一種直譯式語言 — 程式碼由從上到下執行且立即回傳執行結果,你不需要在瀏覽器執行程式之前將程式轉成不同形式。

另外一方面,編譯式語言在被電腦執行之前會轉換(編譯)成另一種形式。舉例來說C/C++編譯成組合語言之後被電腦執行。

兩種形式各有優點,此處不會有探討這些議題。

伺服器端與用戶端程式碼

你也有可能聽過伺服器端客戶端程式語言,尤其在網站開發的內容當中。客戶端程式碼式運行在使用者的電腦中,當瀏覽網頁時,頁面中的客戶端程式碼被下載到電腦裡,接著在瀏覽器中被執行和顯示。在本模組中,中我們只談客戶端的JavaScript

相比之下,伺服器端的程式碼式執行在伺服器,執行後的結果透過瀏覽器下載顯示。舉例來說有許多受歡迎的伺服器端網頁語言,包括PHP、Python、Ruby和ASP.NET。JavaScript也能夠當作伺服器端程式語言,流行的Node.js環境就是一例。你可以取得更多相關資訊在我們的Dynamic Websites – Server-side programming主題中。

動態與靜態程式碼

動態(Dynamic對應上文Dynamic Websites – Server-side programming)一詞用於描述客戶端JavaScript和伺服器端程式語言 — 動態指的是在不同情況下更新網頁/應用程式的畫面以顯示不同內容,就是根據要求生成新內容的能力。伺服器端程式碼在伺服器上動態生成新內容,例如從資料庫中取出數據,而客戶端JavaScript在客戶端的瀏覽器內動態生成新內容,例如建立新的HTML表格,將請求自伺服器的數據插入其中,然後在用戶的網頁中顯示該表格。在兩個情境中詞義稍微不同,但是有關聯,兩種方法(伺服器端和客戶端)通常一起工作。

沒有動態更新內容的網頁被稱為靜態的 — 它只會一直顯示相同的內容。

如何給頁面增加 JavaScript ?

在HTML中使用JavaScript與使用CSS的方法類似。在HTML中CSS藉著<link>元素使用外部樣式(stylesheets)或<style>元素使用內部樣式。JavaScript在HTML中只需要唯一一個朋友 — <script>元素。讓我們一起了解它是如何運作的。

內部的 JavaScript

  1. 首先,下載一份apply-javascript.html範例並存在自己的電腦上適當的路徑裡。
  2. 用瀏覽器與文字編輯器打開剛才下載的範例。你會看到範例HTML檔案建立了一個網頁,其中有一顆可以點的按鈕。
  3. 接著,切換到你的文字編輯器,並且在</head>結尾標籤貼著的前方加入以下程式碼:
    <script>
    
      // JavaScript goes here
    
    </script>
  4. 現在,新增一些JavaScript程式碼在我們的<script>元素之中,讓網頁能夠做些有趣的事 — 在"// JavaScript goes here"那行的下面加入以下程式碼:
    document.addEventListener("DOMContentLoaded", function() {
      function createParagraph() {
        let para = document.createElement('p');
        para.textContent = 'You clicked the button!';
        document.body.appendChild(para);
      }
    
      const buttons = document.querySelectorAll('button');
    
      for(let i = 0; i < buttons.length ; i++) {
        buttons[i].addEventListener('click', createParagraph);
      }
    });
  5. 儲存你的檔案並且重新整理網頁,現在你會發現每當點擊按鈕時會在下方產生一個新段落。

Note: 如果你的範例看似不正常,請按照步驟再操作一次,檢查每一步都正確。 確認你是否下載的範例是.html的檔案?確認你加入的<script>元素正好在</head>標籤的正前面? 確認你輸入的JavaScript程式碼與提供的一模一樣?JavaScript非常注重區分大小寫,所以你輸入的語法要一模一樣,不然很可能出錯。

Note: GitHub上有完整版本的範例apply-javascript-internal.html (see it live too).

外部的 JavaScript

這很不錯,但如果我們想放置我們的 JavaScript 在外部文件的文件應該怎麼做呢?讓我們來探索吧。

  1. 首先,創建一個新的文檔和你的 HTML 文檔同目錄,命名為script.js — 請確定這個文檔是用 .js 為文件副檔名, 這樣它才能識別為 JavaScript。
  2. script.js中,加入以下程式碼:
    function createParagraph() {
      let para = document.createElement('p');
      para.textContent = 'You clicked the button!';
      document.body.appendChild(para);
    }
    
    const buttons = document.querySelectorAll('button');
    
    for(let i = 0; i < buttons.length ; i++) {
      buttons[i].addEventListener('click', createParagraph);
    }
  3. 現在,替換你現有的<script> 元素成如下:
    <script src="script.js" async></script>
  4. 儲存HTML檔案並重新整理你的瀏覽器,接著你會看到一樣的效果。雖然是一樣的效果但是使用的是外部JavaScript檔案。通常的情況下這是編排程式碼的好方法,讓JavaScirpt檔案可以橫跨多的HTML檔案中重複使用。額外上讓HTML檔案更好閱讀,因為沒有很多一塊塊的程式碼印在裡面。

Note: 你可以在GitHub上找到這個版本 apply-javascript-external.htmlscript.js (see it live too).

行內JavaScript處理常式(Inline JavaScript handler)

注意,有時候你會遇到一些JavaScript程式碼存於HTML語法之中。它可能會看起來像這樣:

function createParagraph() {
  var para = document.createElement('p');
  para.textContent = 'You clicked the button!';
  document.body.appendChild(para);
}
<button onclick="createParagraph()">Click me!</button>

你可以在底下的範例中嘗試這種方法。

這個範例與前兩段有完全相同的功能,除了<button>元素包含了一個行內的 onclick 處理常式,使當按鈕按下時,執行函式。

然而,請不要這樣做。用JavaScript汙染你的HTML是一種不好的方法,而且也沒有效率 — 因為你必須加入 onclick="createParagraph()" 屬性在每個你希望JavaScript作用的地方。

使用單純的JavaScript結構,使你可以用一個指令選擇所有的按鈕。以下的程式碼可以達到這個目標,像是:

var buttons = document.querySelectorAll('button');

for (var i = 0; i < buttons.length ; i++) {
  buttons[i].addEventListener('click', createParagraph);
}

這或許看起來比 onclick 屬性還長,但是用在全部的按鈕上,無論頁面上有多少按鈕,也不管按鈕新增還是移除了,JavaScript程式碼都不用改變。

Note: 試著編輯你自己版本的apply-javascript.html,在裡面添加多一點按鈕。當你重新載入網頁,你應該會發現所有按鈕按下去時都會建立一的段落。很簡潔吧!

腳本載入策略(Script loading strategies)

在正確的時機載入腳本牽涉了許多議題,並不如它看起來的簡單!其中一個問題是所有的HTML根據出現順序依序載入。但是假如你的JavaScript中有操作頁面中的HTML元素(精確地來說是DOM, Document Object Model),又在該HTML元素之前載入和執行,你的程式碼可就不會正常運作。

上面的範例中,內部和外部JavaScript範例裡程式碼載入與執行在文件(HTML檔)的開頭,是HTML body 還沒解析之前。這可能會產生錯誤,所以我們用了一些結構避開錯誤。

在內部JavaScript範例中,你可以看到有以下這種結構的程式碼:

document.addEventListener("DOMContentLoaded", function() {
  ...
});

這個事件監聽器,監聽 DOMContentLoaded 事件,這事件的發出是由於HTML body 載入與解析完成。區塊(由左右大括號({})括起的範圍可以稱為區塊)內的程式碼直到 DOMContentLoaded 事件發出後才會執行,因此可以避免錯誤。(你之後會學到關於事件的課程)

在外部JavaScript範例中,我們使用比較現代的JavaScript功能來解決問題,使用 async 屬性告訴瀏覽器碰到 <script> 標籤時,繼續下載其他的HTML內容。

<script src="script.js" async></script>

在這個例子中,腳本(JavaScript程式碼的別稱,或是可以用來稱呼.js檔案)與HTML會同步載入,所以程式碼會正確執行。

Note: 在外部範例裡,我們沒有需要使用DOMContentLoaded事件因為async為我們解決問題了。而在內部範例裡我們沒用async屬性,是因為async屬性只適用在外部的JavaScript腳本。

曾經這個問題有一個老的解決辦法,就是將 script 元素放在 body 元素的下方(僅僅在 </body> 前面),如此一來腳本會在所有HTML解析完後被載入。這個方法有個問題(DOMContentLoaded 解決方法也有相同問題),導致腳本的解析/載入會全面受阻,直到HTML DOM載入完成。對於擁有許多JavaScript2的大型網站,這會拖慢網站,造成主要的效能問題。這就是為何async會被加入瀏覽器之中!

async and defer

其實有兩個方法避免阻塞腳本 — asyncdefer,讓我們一起看看兩者的區別。

Async的腳本下載時不會阻塞網頁渲染,在下載完成後馬上執行。它並不向你保證他會按照特定的順序執行,只會不妨礙網頁中其他部分顯示。async最好的用法是當網頁中的腳本間彼此獨立運行,腳本們不依賴彼此。

例如你有以下的 script 元素

<script async src="js/vendor/jquery.js"></script>

<script async src="js/script2.js"></script>

<script async src="js/script3.js"></script>

你不能靠出現順序當作載入順序。 jquery.js 可能會在 script2.jsscript3.js 的之前或之後載入,在之後載入這個情況下,任何函式如果依賴 jquery 會產生錯誤,因為在其他腳本運行前 jquery 還沒被定義。

Defer會按照出現順序執行腳本們,當腳本與內容都下載了。

<script defer src="js/vendor/jquery.js"></script>

<script defer src="js/script2.js"></script>

<script defer src="js/script3.js"></script>

全部有 defer 屬性的腳本會依據在網頁出現的順序載入。所以第二個範例中,我們可以確定 jquery.js 會在 script2.jsscript3.js 之前載入, script2.js 會在 script3.js 之前載入。

整理一下就是:

  • 如果你的腳本不用等待解析,可以獨立運行沒有相依,請用 async
  • 如果你的腳本需要等待解析,且依賴其他腳本,請用 defer ,並根據你想要瀏覽器執行的順序安排 <script> 元素的次序。

註解

如同HTML和CSS,在JavaScript程式碼中也可以寫註解,註解會被瀏覽器忽略,僅用來提供你的同伴開發者說明(或者是你,在六個用後回還看你的程式碼時,忘記你做過了什麼),說明程式碼如何運作。註解非常有用,你應當多多利用,尤其是大型應用程式。註解有兩種形式:

  • 單行註解,寫在雙(正)斜線(//)之後,例如:
    // I am a comment
  • 多行註解,寫在/*和*/之間的文字,例如:
    /*
      I am also
      a comment
    */

舉例來說,我們可以加入註解在我們的上一個範例中的JavaScript,像是:

// Function: creates a new paragraph and append it to the bottom of the HTML body.

function createParagraph() {
  var para = document.createElement('p');
  para.textContent = 'You clicked the button!';
  document.body.appendChild(para);
}

/*
  1. Get references to all the buttons on the page and sort them in an array.
  2. Loop through all the buttons and add a click event listener to each one.

  When any button is pressed, the createParagraph() function will be run.
*/

var buttons = document.querySelectorAll('button');

for (var i = 0; i < buttons.length ; i++) {
  buttons[i].addEventListener('click', createParagraph);
}

摘要

所以你已經踏出在JavaScript世界中的第一步,我們從理論開始,逐漸習慣為何要用要使用JavaScript,還有你可以用它做什麼。別的先不提,一路上我們看了一些程式碼範例,學到JavaScript如何和你網站中其餘程式碼放在一起。

目前為止JavaScript看起來可能有一點嚇人,然而不用擔心—在本課程中我們會帶著你,用簡單合理的步調向前。 在下一篇文章中我們將會直接跳進現實之中,帶你直接跳入並建立你自己的JavaScript範例。

在這個模組

文件標籤與貢獻者

標籤: 
此頁面的貢獻者: RishYang, mdnwebdocs-bot, mhlemonh, laichenghuan, Rowen, MLJ
最近更新: RishYang,