avascript 等於 ECMAScript + 宿主環境。宿主環境提供了一系列的全局對象,例如Node.js提供的require, console等;瀏覽器提供的DOM、BOM對象。本節課咱們便來了解瀏覽器,熟悉客戶端腳本開發和調試。javascript
Javascript 已經成爲 Web 頁面邏輯的默認腳本語言,能夠直接在 HTML 文件中引入而不需代表腳本語言。Javascript 使用 <script>
標籤引入,該標籤能夠出如今 <head>
中,也能夠出如今<body>
中。css
在HTML4中,
<script>
標籤須要指定腳本類型:type="text/javascript"
。如今已經沒必要這樣作了。JavaScript 是 HTML5 默認的腳本語言。html
在HTML中引入Javascript有兩種方式:內嵌JavaScript和外部JavaScript文件。java
內嵌JavaScript(Inline JavaScript)是指在HTML中添加<script>
標籤,並將JavaScript代碼直接寫在標籤的內容中。jquery
<!-- embeded-script.html --> <html> <head> <script> console.log("I'll give you an alert!"); alert('This is an alert.'); </script> </head> <body> script is embeded in HTML </body> </html>
將上述代碼另存爲embeded-script.html
並用瀏覽器打開它,你將會看到一個彈出窗口。web
在介紹CSS時提到,爲了分離HTML中的樣式,咱們把全部樣式規則都移到獨立的CSS文件中,而後在HTML中加以引入。這使得HTML更加容易理解和維護,同時也對搜索引擎、屏幕閱讀器更加友好。ajax
外部腳本也是同樣的道理,除了在極少數狀況下(少許的JavaScript、Google Analytics等),JavaScript老是應看成爲外部資源來引入到HTML中。編程
爲了方便維護和複用,咱們經常將不一樣語言的代碼分離到不一樣的文件。更重要的是,這樣的組織方式會讓你的代碼更優雅!瀏覽器
只須要將<script>
標籤內容留空,並添加src
屬性:服務器
// file: script.js console.log("I'll give you an alert!"); alert('This is an alert.');
<!-- file: import-script.html --> <html> <head> <script src="./script.js"></script> </head> <body> script.js has been imported. </html>
分別保存上述兩個文件,置於同一目錄下並打開HTML,會有相同的效果。
HTML爲典型的流文檔。即:自上而下分紅一行一行, 並在每行中按從左至右依次排放元素。正由於HTML流式文檔的特徵,其中的<script>
也是按從上到下的順序執行的。HTML之因此採用這樣的設計是由於互聯網架設之初網絡速度頗有限,流式文檔能夠在載入的過程當中就能夠逐步地顯示。**
文檔對象模型(Document Object Model,DOM)是中立於平臺和語言的接口,它容許程序和腳本動態地訪問和更新文檔的內容、結構和樣式。一樣地,DOM 也是 W3C(萬維網聯盟)的標準。換句話將,DOM 定義了訪問 HTML 和 XML 文檔的標準。
咱們關心的 HTML DOM 則是 DOM 的延伸,它包括 HTML 的標準對象模型、HTML 的標準編程接口、W3C DOM 標準。HTML DOM 定義了全部 HTML 元素的對象和屬性,以及訪問它們的方法。
說了這麼多,上述關於 DOM 和 HTML DOM 的概念或許在你有必定 Web 開發經歷時纔會理解。如今你能夠認爲 DOM 就是用來定義如何組織 HTML 結構、如何操做 HTML 元素的。固然,咱們指的是從Javascript中操做 HTML 元素。
HTML DOM 將 HTML 文檔視做樹結構。這種結構就是咱們常講的 DOM 樹:
若是你須要更多關於DOM的信息,請參考 W3C Schrool 的 DOM 教程。
整個 HTML 文檔是由樹狀組織的節點及其屬性構成的。那麼如何在Javascript中操做它呢?請看例子:
<!-- file: dom.html --> <html> <body> <ul id="fruits"> <li>Carrot</li> <li>Apple</li> <li>Banana</li> </ul> <script src='./dom.js'></script> </body> </html>
// file: dom.js // 得到id爲fruits的節點 var ul = document.getElementById('fruits'), carrot = ul.firstElementChild; ul.removeChild(carrot); var pear = document.createElement('li'); // 設置pear的style屬性 pear.setAttribute('style', 'color: red'); // 設置pear的內容 pear.innerHTML = 'pear' ul.appendChild(pear);
這段代碼給出了一個簡單的操做DOM元素過程。找到id
爲fruits
的標籤並刪除其第一個子節點;而後建立一個新的元素pear
並添加到<ul>
中。更多 DOM 操做的方法請參考 W3C School: DOM 方法。
正是 DOM 事件使得頁面能夠與用戶進行交互,例如點擊、移入、移出、滾動等。一樣地,來個例子:
<!-- file: event.html --> <html> <head> <script src='./event.js'></script> <head> <body> <div id='block' onmouseover="over(this)" onmouseout="out(this)"> Mouse Over Me ! </div> </body> </html>
// file: event.js function over(obj) { obj.innerHTML="mouse is over!!!" } function out(obj) { obj.innerHTML="mouse is out..." } window.onload = function(){ var div = document.getElementById('block'); div.setAttribute('style', "background:lightgreen; width:200px;height:50px; margin: 50px;"); };
經過設置HTML元素的屬性,能夠設置其事件處理函數。咱們在<div>
上綁定了兩個事件:mouseover
(鼠標移入)和mouseout
(鼠標移出)。
那麼window.onload
是什麼呢?注意到咱們在<head>
中引入了event.js
,然而由於HTML是流式文檔,在執行event.js
時,<body>尚未獲得渲染,此時直接document.getElementById('block')
只會獲得空。所以咱們須要綁定窗口載入事件的處理函數,在窗口已經載入後,再進行 DOM 操做。
而window
即是咱們接下來要介紹的 BOM。
瀏覽器對象模型 (Browser Object Model,BOM) 使 JavaScript 有能力與瀏覽器「對話」。雖然尚無正式標準,但大多現代瀏覽器都實現了相同的交互方法和屬性。其功能包括:操做瀏覽器窗口、瀏覽歷史與導航、Cookie操做、各種提醒框等。
window
是瀏覽器中一個特殊的對象。全部 JavaScript 全局對象、函數以及變量均自動成爲 window 對象的成員。全局變量是 window 對象的屬性。全局函數是 window 對象的方法。
window.location
對象用於訪問當前 URL,或者導航到新的頁面。location
有以下幾個屬性:
hostname
:web 主機的域名
pathname
:當前頁面的路徑和文件名
port
:web 主機的端口
href
:當前url,對它賦值能夠實現重定向
reload()
:這是一個方法,調用後會刷新當前頁面
除了window.location
外,還有window.history
提供瀏覽器歷史的操做,經常使用的有:
history.back()
:與在瀏覽器點擊後退按鈕相同
history.forward()
:與在瀏覽器中點擊按鈕向前相同
更多瀏覽器導航的BOM對象能夠參考W3C School:location、W3C School:history。
彈出窗口對象使用簡單方便,但因其交互方式生硬,一般只用於調試。能夠在 JavaScript 中建立三種消息框:警告框、確認框、提示框。
alert("some message")
:警告框,點擊肯定按鈕才能繼續進行操做;
confirm("something")
:確認框,點擊肯定或者取消才能繼續進行操做,相應地,返回值爲true
或false
;
prompt("something")
:提示框,輸入內容,並點擊確認或取消才能繼續進行操做,相應地,返回輸入內容,或者null
(若是取消)。
注意這些彈窗都會阻塞當前的Javascript進程。
console
咱們已經很熟悉了,除了經常使用的console.log()
外,還有console.error()
,console.info()
,console.debug()
等用以日誌分級的函數。
console
咱們在Node.js的課程中已經屢次使用,但console並不是 ECMAScript 標準提供的對象。只是瀏覽器和 Node.js 都實現都提供了這樣的全局對象而已。
AJAX(Asynchronous JavaScript and XML,異步的 JavaScript 和 XML),是用來與服務器交換數據並更新部分網頁的技術,避免了從新加載整個頁面。
能夠說AJAX是現代化的頁面的標誌,可用來建立動態性極強的 web 界面,如今咱們來學習它!絕大多數瀏覽器都提供了 XMLHttpRequest
對象來完成 AJAX。爲了理解 AJAX 是如何工做的,咱們仍是首先看一個案例:
這裏有一個按鈕,點擊按鈕將會向服務器請求當前時間,服務器返回後將時間顯示在下面。每次點擊按鈕時間都會更新,但頁面不會刷新。
爲了實現上述的效果,首先須要在頁面上顯示相似這樣的元素:
<input type='button' onclick='ajaxload()' value='Click Here to Get Data!'> <div id='result'></div>
點擊按鈕時將會調用ajaxload()
函數,在該函數中進行 AJAX 請求:
function ajaxload(){ var result = document.getElementById('result'); // 建立一個 AJAX 請求 var xhr = new XMLHttpRequest(); // 打開URL:/date xhr.open('GET', '/date', true); // xhr 狀態改變的處理函數 xhr.onreadystatechange=function(){ // 狀態爲4表示響應已就緒;狀態碼200表示成功的響應 if (xhr.readyState==4 && xhr.status==200) // 顯示響應文本 result.innerHTML=xhr.responseText; } xhr.send(); }
更多關於
readyState 的信息
,參見W3C School:ReadyState
上述的代碼在ajax.html
中。除此以外,咱們還須要一個服務器來處理這些請求。當請求根目錄/
時,返回這個 HTML
文件;當請求/date
時,返回當前時間。下面服務器代碼ajax.js
:
// file: ajax.js var http = require('http'), fs = require('fs'), html = fs.readFileSync('./ajax.html', 'utf8'); http.createServer(function (req, res) { switch(req.url){ case '/': res.writeHead(200, {'Content-Type': 'text/html'}); res.write(html) break; case '/date': var date = new Date(); res.writeHead(200, {'Content-Type': 'text/plain'}); res.write(date.toString()) break; } res.end(); }).listen(1337, '127.0.0.1')
這段代碼的意圖應該比較容易理解吧?咱們在下面的Chrome調試中,會詳細地介紹這些代碼產生的效果。
到這裏,咱們已經介紹了經常使用的幾個瀏覽器全局變量。window
下的全局變量還有:
innerHeight/innerWidth
:瀏覽器窗口內部高度/寬度;
navigator
:包含有關訪問者瀏覽器的信息;
screen
:訪問者屏幕的寬度,以像素計;
setTimeout()/clearTimeout()
:定時器/取消定時;
document.cookie
:如今多數網站使用Cookie來識別用戶。
通常的網站都會包含客戶端腳本,這些腳本的數量甚至比服務器代碼還要多,尤爲是單頁APP這種交互性優秀的站點。
jQuery 是一個javascript基礎框架,極大地方便了客戶端腳本的編寫,這裏只作簡要介紹,此後的項目開發中,你會見到衆多的jQuery代碼。jQuery提供的API包括:
DOM操做:選擇、讀取和更改DOM元素的內容、屬性;
AJAX:異步網絡請求;
動畫效果:滑動、延遲、淡入淡出等;
事件處理:鍵盤/鼠標事件、瀏覽器事件、表單事件等;
表單:表單的提交、表單的序列化、控件焦點變化等。
爲了表現jQuery的強大,咱們引入jQuery,使用jQuery從新實現 DOM 一節中的參考代碼dom.html
和dom.js
。首先在dom-jquery.js
以前引入jquery.js
:
... <script src='./jquery.js'></script> <script src='./dom-jquery.js'></script> ...
// file: dom-jquery.js // 選擇 id 爲 fruits 的元素集合(該集合中只有一個元素,即 ul ) var $ul = $('#fruits'); // 找到該元素的第一個子元素(即 li)並將其移除 $ul.find(':first-child').remove(); // 建立一個 li 元素,並設置其 color 樣式爲 red,其內容爲 pear var $pear = $('<li>') .css('color', 'red') .html('pear'); // 將 pear 添加到 ul 中 $ul.append($pear);
若是你是初識jQuery,可能會奇怪$是什麼。其實$在javascript中是一個合法的標識符,也就是說
$
能夠用來命名變量。
jQuery 提供的全局變量:$
,它稱爲 jQuery 對象。習慣上,經過 jQuery 選擇符獲得的集合通常命名爲以$起始的字符串,例如 $ul
。
$ul
是一個集合,只不過它只有一個元素。若是使用 $li = $('li')
,那麼該集合便會有3個元素,jQuery的全部方法都是對整個集合進行操做的。
Chrome和Firefox是Web開發中經常使用的調試工具,咱們以Chrome爲例。使用如下的任何一種方式均可以打開Chrome調試窗口:
在任何一個頁面上,點擊右鍵,選擇「審查元素」;
快捷鍵F12
;
設置 -> 更多工具 -> 開發者工具。
打開的調試窗口中,有8個標籤頁。經常使用的有 Elements、Network、Sources、Console。
Elements 中,咱們能夠查看頁面元素,在左側能夠點選某一個元素,該元素會在頁面上高亮,同時在右側顯示該元素的全部樣式。這些樣式仍是可編輯的。
Network 中,能夠查看當前頁面的全部網絡請求。好比 AJAX 一節中咱們會發送多個請求,在 Network 標籤頁中,能夠看到訪問頁面時的請求,以及點擊按鈕獲取數據時的請求,以下圖所示:
從上圖中能夠看到這兩個請求:
第一個請求的URL是localhost
,方法爲 GET,響應狀態碼爲 200,響應的Content-Type
爲text/html
,響應大小爲712B,文件大小爲567B(其他爲協議頭所佔空間),載入時間爲13毫秒。
第二個請求Content-Type
爲text/plain
,這是在服務器代碼中決定的。另外其initiator
即初始化該請求的代碼,在首頁(index
)的第14行,咱們這一行的代碼爲:
xhr.send();
text/html
指示瀏覽器這是一個HTML文件,瀏覽器便會把它渲染爲一個Web文檔。若是將Content-Type
設置爲text/plain
,瀏覽器則會直接顯示HTML源碼。
不只如此,咱們還能夠點擊第二個請求來查看其詳情,以下圖:
右側詳情窗口中有5個標籤頁,經常使用的是 Headers、Preview、Response。其中 Headers 中給出了請求和響應的全部頭字段;Response 則給出了響應體的內容,這裏是:
Mon Mar 30 2015 21:32:17 GMT+0800 (CST)
它就是xhr.responseText
的值。
Sources標籤頁下,能夠查看當前網站的HTML,及其引入的全部CSS、Javascript文件。重要的是,在Javascript文件中的任何一行,咱們均可以設置斷點,腳本將會在這一行停下來。觸發斷點時,咱們能夠查看斷點所在的做用域內的全部變量的值,以下圖所示:
右側窗格顯示了局部變量、監視變量以及調用棧。右側窗格的上方有繼續、下一步、進入函數、跳出函數、禁用斷點等按鈕。
還能夠切換至Console,在當前做用域下執行任何Javascript語句。
Console與Node.js的控制檯相似,這是一個Javascript的交互式環境。在這裏能夠執行任何Javascript語句,如圖:
上圖中咱們首先執行了:
new Date()
控制檯中輸出了這個語句的返回值。接着執行:
console.error('test error')
咱們便在控制檯看到了一則錯誤,其內容爲test error
。
在斷點觸發時(例如上圖中的狀況),在控制檯能夠訪問當前做用域的任何對象,讀取或設置它們的值,甚至在這裏調用做用域內的任何函數。如圖即是輸出了上述斷點觸發時的xhr
對象。
本文由Harttle創做,轉載需署名做者且註明文章出處