簡介
?迄今為止,?使用HTML+CSS構(gòu)建出的頁面始終缺乏“交互性”,為了能夠?qū)崿F(xiàn)網(wǎng)頁和你之間的互動,瀏覽器引入了用于操作html內(nèi)容的腳本語言——JavaScript(JS),時至今日,JS在web開發(fā)界已經(jīng)發(fā)展成為最火最熱的語言,因此你一定不可錯過它
目標(biāo)
- 了解什么是腳本語言,以及腳本語言和靜態(tài)編譯語言(如C++)的區(qū)別
- 了解JavaScript并嘗試使用它
- 了解HTML的DOM模型
- 了解事件和回調(diào)函數(shù)
任務(wù)
- 使用JavaScript構(gòu)建具有交互功能的網(wǎng)頁
預(yù)期時間
- 1-2天
有關(guān)JS
JS是當(dāng)今最為火爆的WEB開發(fā)語言了,在正式開始講解知識之前我們來扯一點題外話
為什么要學(xué)習(xí)JavaScript
HTML定義了網(wǎng)頁的內(nèi)容,CSS描述了網(wǎng)頁的布局和樣式,JS則定義了網(wǎng)頁的行為,因此為了構(gòu)建完整的網(wǎng)頁應(yīng)用,JS是必不可少的。
JS是目前瀏覽器上唯一通用的可操作的HTML的語言,換句話說你除了JS沒有第二個選擇。
毫不夸張的說,JavaScript是構(gòu)建當(dāng)今web世界的支柱語言,學(xué)習(xí)JS你可以構(gòu)建任何類別的應(yīng)用:網(wǎng)頁,APP,服務(wù)端統(tǒng)統(tǒng)可以用一個語言搞定。
但是...
- JS不是一門嚴(yán)謹(jǐn)?shù)恼Z言,有著很多致命的設(shè)計缺陷,盡管現(xiàn)在已經(jīng)得到了一定的改進(jìn)
- JS雖然用途十分廣泛,但在除了前端以外的地方略顯吃力
- JS的語法不嚴(yán)謹(jǐn)在提升了它的靈活性的同時也使得極易寫出規(guī)范性差,不可控的代碼,因此雖然上手簡單,但是想要寫出高質(zhì)量的JS代碼并不是一件容易的事情
本節(jié)課如何講解JS
這節(jié)課里我們不會針對JS做過多深入的講解,主要目的集中在:
- 了解腳本語言的特性
- 使用JS構(gòu)建具有交互性的網(wǎng)頁
如果你想深入學(xué)習(xí)JS和前端,在后期應(yīng)用篇(前端)中將會詳細(xì)介紹相關(guān)的內(nèi)容,本節(jié)課程的末尾處也會給出一些比較新的JS教程(千萬不要學(xué)習(xí)老版本的JS)供你自學(xué)。
了解JavaScript和腳本語言
我們假定學(xué)習(xí)本課的同學(xué)都有一定的編程基礎(chǔ),想必絕大多數(shù)人接觸的都是像C,C++以及Java這一類比較傳統(tǒng)的靜態(tài)編譯語言。JS則是90年代開始流行的幾大腳本語言之一,由于腳本語言和編譯語言存在較大的差別,所以下面的JS基礎(chǔ)教學(xué)中將會同時展開說明一下腳本語言和編譯語言的差別
運行JS
JS是運行在瀏覽器上的語言(盡管現(xiàn)在它已經(jīng)可以運行在其他環(huán)境中了),因此你需要在瀏覽器里才能運行JS代碼,我們可以通過html文件引入JS,主要有以下兩種方式:
1.在html中使用<script>標(biāo)簽
<script>標(biāo)簽可以插在<head>或者<body>標(biāo)簽中,內(nèi)部的內(nèi)容就是js代碼。
實例
<!DOCTYPE html>
<html>
<body>
<h1>我的 Web 頁面</h1>
<p id="demo">一個段落</p>
<button type="button" onclick="myFunction()">嘗試一下</button>
<script>
function myFunction()
{
document.getElementById("demo").innerHTML="我的第一個 JavaScript 函數(shù)";
}
</script>
</body>
</html>
2.外鏈引入
跟.css文件一樣,js也可以通過外部來引入,方式是使用<script>標(biāo)簽的src屬性來引入外部的js文件
實例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JS Demo</title>
<script src="./4-1.js"></script>
<!--使用外鏈引入js-->
</head>
<body>
<button id="b1" onclick="alertB1()">Click Me</button>
</body>
</html>
對于較大的項目一般推薦使用引入外鏈的方式
預(yù)備:了解JS輸出內(nèi)容的方式
一個程序要和你交互,至少應(yīng)該能夠輸出內(nèi)容(比如C++里的cout),為了能夠順利進(jìn)行下面的教學(xué)和演示,你至少要先學(xué)會讓JS輸出內(nèi)容給你...
JS基于瀏覽器運行,因此主要借助瀏覽器來進(jìn)行輸出
有兩個調(diào)試階段最常用的輸出方式
alert()函數(shù)
調(diào)用alert()函數(shù)將會彈出一個窗口并將傳入的參數(shù)打印出來。
實例(寫在body中并打開頁面試試?。?/p>
<script>
alert("Hey You!!");
</script>
alert()可以打印絕大多數(shù)的數(shù)據(jù)類型,包括數(shù)組和對象在內(nèi)
console.log()函數(shù)
這個函數(shù)會把接受的變量以及詳細(xì)的類型打印到瀏覽器的控制臺中(回顧第一講的瀏覽器開發(fā)者工具,選擇它的CONSOLE選項卡就能看到控制臺),此外,控制臺中也會輸出一些有關(guān)的輔助信息(比如警告,錯誤等)。
實例(同樣寫在body中)
<script>
var obj = {
name: "mark",
sex: "male"
};
console.log(obj);
</script>
打開頁面后查看控制臺,就可以看到結(jié)果了

變量的定義與數(shù)據(jù)類型
腳本語言中的變量有以下幾個特點:
- 沒有類型(int,string,char...),任何一個變量都可以儲存任何類型的數(shù)據(jù)
- 無需提前聲明就可以直接使用
語法示范:
- 聲明變量使用var關(guān)鍵字,可以儲存任意類型的數(shù)據(jù)
var myInt = 123; // 整數(shù)
var myDecimal = 12.1; // 浮點數(shù)
var myStirng = "Hello JS"; // 字符串
var myArray = [1,"hello",12.3,{name:"lux"}]; // 數(shù)組(可以存放任意類型,任意數(shù)量的值)
var myObject = {name:"lux",sex:"male",age:"18"} // 對象,就是鍵值對
var myFunction = function(){ return "this is a funciton" } // 函數(shù)也可以是變量,是不是很神奇
- 變量可以隨意轉(zhuǎn)換類型,也可以不用聲明就直接用
var myVar = 123;
myVar = "Hello Var"; // 自由轉(zhuǎn)換類型
myAnotherVar = 1; // 不用var聲明直接也可以使用變量,不過不推薦
你應(yīng)該特別留意數(shù)組和對象兩種類型,它們的作用方式和靜態(tài)語言存在很大的不同,下面給出較為詳細(xì)的教程:
注*:暫時(在本節(jié)課中),你不必太深入的了解這些數(shù)據(jù)類型
流程控制
流程控制無非是老生常談的選擇,順序和循環(huán),這一塊JS的語法基本和C/C++一致,因此不過多贅述,點擊下面的鏈接查看詳細(xì)內(nèi)容:
函數(shù)
函數(shù)將在JS中被重新定義。JS是一門函數(shù)式編程的語言,這意味著函數(shù)是“第一等公民”。
最大的特征有以下幾點:
- 函數(shù)可以當(dāng)做變量
- 函數(shù)可以當(dāng)做另一個函數(shù)的參數(shù)或者返回值
(暫時只列出這么多,后面會有專門的章節(jié)來講解函數(shù)式編程)
基本定義
js中的函數(shù)一定要用function關(guān)鍵字聲明,另外由于變量沒有類型,所以函數(shù)也不用指定參數(shù)的類型和返回值的類型,一個典型的函數(shù)大概長下面這樣:
funciton 函數(shù)名(參數(shù)1,參數(shù)2...) {
函數(shù)代碼
return 返回值
}
函數(shù)可以沒有名稱,這樣的函數(shù)被稱為匿名函數(shù),它可以保存到變量
用變量儲存函數(shù)
演示一個用變量調(diào)用匿名函數(shù)的例子
var addMe = function(var1,var2){
return var1+var2;
};
var a = 1,b = 2;
console.log(addMe(a,b)); //利用變量來調(diào)用,輸出為3
將函數(shù)當(dāng)做值來傳遞
最常用的情景是把函數(shù)當(dāng)做參數(shù)來傳遞,這樣做可以極大的擴充函數(shù)的功能,可以參考下面這個實例
// 定義兩個匿名函數(shù)
var sayHello = function(name) {
console.log("hello, "+name);
};
var sayHi = function(name) {
console.log("hi, "+name)
};
var arr = ['mark','ann','ouxu','molybdenum','ruby'];
// 一個用于對arr數(shù)組進(jìn)行操作的函數(shù),第一個參數(shù)是要操作的數(shù)組,第二個參數(shù)是需要對數(shù)組中的元素所應(yīng)用的函數(shù)
function operateArr(paramArr,func) {
for (var i=0;i<5;i++) {
func(arr[i]);
}
}
// 傳入不同的函數(shù)來執(zhí)行
operateArr(arr,sayHello);
operateArr(arr,sayHi);
執(zhí)行的結(jié)果如下:

我們把sayHi和sayHello兩個函數(shù)稱為回調(diào)函數(shù),這個概念十分有用,我們下面要講的事件機制中大量應(yīng)用了回調(diào)函數(shù)(不過看上去沒有這么復(fù)雜)
有關(guān)函數(shù)的作用域,以及函數(shù)式編程的問題會在后面的篇幅中進(jìn)一步講解,現(xiàn)在你需要了解的是函數(shù)在js中擁有非常高的地位,后面要講到的有關(guān)實現(xiàn)交互的內(nèi)容基本都是靠各種各樣的函數(shù)來實現(xiàn)的。
總之,先把函數(shù)當(dāng)成你編寫js代碼的最小結(jié)構(gòu)塊吧!
代碼的執(zhí)行
腳本語言和編譯語言不同,不需要編譯成可執(zhí)行的二進(jìn)制文件之后運行,它是解釋運行的。
實際上它工作的原理是由JS執(zhí)行器讀取JS文件后,一行一行代碼的讀取并執(zhí)行,不會產(chǎn)生任何中間文件,程序運行的過程,就是由執(zhí)行器讀取代碼文件的過程,脫離了執(zhí)行器(也叫解釋器或者代碼引擎)代碼就和純文本沒有任何區(qū)別了。
一個典型的情況是,即便你的腳本中存在錯誤,只要執(zhí)行的過程中沒有執(zhí)行到錯誤所在的地方,它都還能正常運行。
使用JS來和用戶交互
DOM節(jié)點
JS是通過HTML的DOM模型來控制HTML內(nèi)容的,首先我們來了解一下什么是DOM。
DOM是Document Object Model的縮寫,也就是文檔對象模型。HTML的DOM就是整個頁面元素的邏輯結(jié)構(gòu),包含了元素和元素之間的層級關(guān)系,你可以簡單把它理解成一顆元素樹,就像下面這樣:

所有的HTML都可以整理成這樣的一棵DOM節(jié)點樹。JS可以對DOM節(jié)點進(jìn)行各種操作:查找,獲取,修改屬性,內(nèi)容,響應(yīng)事件....
在JS中我們通常使用document對象來獲取整個頁面的DOM
JS獲取頁面元素的手段
下面介紹的函數(shù)都是document對象提供的方法,你可以像document.getElementById("main")這樣使用。
HTML的內(nèi)容參考上一節(jié)的基礎(chǔ)HTML(3-1.html)
根據(jù)id查找(最有用)
還記得我們上節(jié)課中講到的元素的id屬性嗎,它是一個元素的唯一標(biāo)識符,用它來獲取元素再合適不過了。
使用getElementById()方法。
你可以使用一個變量來保存查找到的DOM節(jié)點對象:
var x = document.getElementById("card1");
// 獲取id為card1的dom元素
根據(jù)類名(class)來查找
使用getElementsByClassName()方法,請注意方法名中Element為復(fù)數(shù)形式,這是因為同一class可能有多個元素,這時候此方法返回的是該class所有的元素的集合
一個簡單的使用示范:請注意如果你是在body中書寫js代碼,一定要把這段代碼放在你能獲取的DOM節(jié)點后面,否則由于頁面的解析是從上到下的,在你執(zhí)行代碼時將無法得到想要的DOM節(jié)點。
<body>
<div class="card" id="card1">
<p>this is card 1</p>
</div>
<div class="card" id="card2">
<p>this is card 2</p>
</div>
<script>
var cards = document.getElementsByClassName('card');
var cardCount = cards.length; // 獲取card類有多少個元素
for (var i=0;i<cardCount;i++) {
console.log(cards[i]); // 使用索引就可以取出每一個元素的對象了
}
</script>
</body>
根據(jù)標(biāo)簽名來查找
使用getElementsByTagName()方法,該方法返回的同樣是集合,由于同名標(biāo)簽在整個頁面中非常多,所以這個方法經(jīng)常用于嵌套取出某個DOM節(jié)點內(nèi)的指定標(biāo)簽
查看下面的示范并注意理解嵌套式的查找:
var x=document.getElementById("card1"); // x是card1
var y=x.getElementsByTagName("p"); // y是card1里的p標(biāo)簽
操作DOM
當(dāng)你獲取了DOM節(jié)點之后,就可以對它做很多事情:讀取、操作DOM的屬性、內(nèi)容和樣式...
下面會演示一些十分常用的DOM操作
改變HTML內(nèi)容
你可以使用document.write()直接在script標(biāo)簽,也就是代碼執(zhí)行的位置直接寫入內(nèi)容:
<body>
<div>
<script>
document.write("<p>這是一段由JavaScript創(chuàng)建的文字</p>");
</script>
</div>
</body>
更為常見的做法是,通過上面所述的方法獲取DOM節(jié)點后,使用innerHTML屬性來訪問和修改對應(yīng)節(jié)點的內(nèi)容
<body>
<h1 id="header">這是老標(biāo)題內(nèi)容...</h1>
<script>
var header =document.getElementById("header");
header.innerHTML = "這是新標(biāo)題內(nèi)容..."; // 修改h1標(biāo)簽里的文字
</script>
</body>
改變元素的樣式
可以使用DOM對象的style屬性來訪問和修改對應(yīng)元素的樣式,你可以發(fā)現(xiàn)js中DOM對象的屬性和對應(yīng)html的元素的屬性存在著對應(yīng)的關(guān)系
<body>
<p id="para1" style="color:red">其實我是藍(lán)色文字</p>
<p id="para2" style="font-size:2px">我的字很大</p>
<script>
document.getElementById("para1").style.color = 'blue';
document.getElementById("para2").style.fontSize = '30px';
</script>
</body>
事件和回調(diào)函數(shù)
現(xiàn)在我們已經(jīng)可以通過JS控制HTML的各種內(nèi)容了,但是整個頁面仍然缺乏交互性:所有的腳本都是預(yù)先寫好,在網(wǎng)頁打開時就自動調(diào)用了的,有沒有辦法讓用戶在瀏覽網(wǎng)頁的時候主動觸發(fā)腳本并執(zhí)行呢?
這時候我們需要引入事件編程的概念,事件就是在操作頁面過程可能發(fā)生的諸多動作,比如:點擊一個按鈕,拖動一個元素,將光標(biāo)移動到某個元素上...你可以把這些事件理解成開關(guān)或者觸發(fā)器,我們一般會綁定函數(shù)到某個事件上,當(dāng)事件被觸發(fā)的時候,該函數(shù)就會被自動調(diào)用,我們也把這種函數(shù)成為事件的回調(diào)函數(shù)。
來看一個經(jīng)典的例子:通過點擊一個按鈕來彈出一個警告框
<body>
<script>
function alertSth(){
alert("你點我干啥");
} // 定義回調(diào)函數(shù)
</script>
<button onclick="alertSth()">點我試試</button>
<!--通過onclick屬性把alertSth()函數(shù)綁定到該按鈕的點擊事件上-->
</body>
HTML中存在非常多的事件,不同類別的元素?fù)碛械氖录膊槐M相同,限于篇幅這里就不一一展開了,點擊下面的鏈接深入了解一下事件機制吧
有了事件的存在,結(jié)合之前JS操作DOM節(jié)點的強大功能,我們就擁有了構(gòu)建高可交互性網(wǎng)頁的基石了。
小結(jié)
JavaScript是一門神奇的腳本語言,它十分簡單易學(xué),也十分好玩(在不深入了解的前提下),目前IT界正在不斷的修改和完善JavaScript語言,并嘗試統(tǒng)一它的標(biāo)準(zhǔn)。
決定學(xué)習(xí)JS的同學(xué)們,至少應(yīng)該學(xué)習(xí)ES6版本的新JS,下面給出兩個大牛寫的JS教程:
JS由于起初設(shè)計的不嚴(yán)謹(jǐn),導(dǎo)致了一些非常迷亂的現(xiàn)象(最著名的是那張JS的真值表),你學(xué)習(xí)的過程中也可能會多多少少遇到一些坑,記得編寫js代碼時保持態(tài)度的嚴(yán)謹(jǐn),可以盡可能的避免一些錯誤的產(chǎn)生。
本節(jié)課是前端認(rèn)知篇的最后一篇,HTML+CSS+JS三者的組合已經(jīng)足夠你構(gòu)建任意類型的網(wǎng)頁頁面,下一課中我們將會對這幾節(jié)課做一個整理總結(jié),并給出一個挑戰(zhàn)實例供你練習(xí)。