JavaScript 語言正越來越受歡迎,可以說是是互連網上最突出的語言之一。你可以跨平台和瀏覽器使用它,其並不排斥後端語言。現在有許多不同的開發庫——有些非常棒—— 這些庫對開發很有協助,比如說加快了開發的時間等等。問題是,有時候這些庫與原始語言之間很是有一些距離,這使得剛入門的開發人員缺乏一種對語言的基礎瞭解。
本文通過全面列舉基礎的JavaScript概念這一方式來闡述該語言的基本原理,以此來為初學者提供一個對語言的基本瞭解,隨處可見的代碼例子則是用來說明所有的這些概念是如何在語言中體現出來的。
瞭解JavaScript語言
JavaScript語言是一種免費的用戶端指令碼語言,其能夠讓你往超文字標記語言 (HTML)(Hypertext Markup Language,HTML)頁面中加入互動行為。用戶端(client-side)意味著JavaScript運行在瀏覽器中,而不是用在伺服器端。在網頁被伺服器送達並被瀏覽器載入後,用戶端指令碼就允許使用者與網頁進行互動。例如,Google Maps就是使用JavaScript語言來支援使用者與地圖之間的互動的,互動的方式有移動地圖、放大和縮小等。沒有JavaScript語言的話,網頁需要為每次和每個使用者的互動行為進行重新整理,當然,除非頁面用到了諸如Adobe Flash或是Microsoft® Silverlight一類的外掛程式。JavaScript語言不需要外掛程式。
因為JavaScript語言為載入後的網頁提供使用者互動行為,因此開發人員通常會用它來實現下面的一些功能:
1. 動態添加、編輯和刪除HTML元素及它們的值。
2. 在提交之前校正表單。
3. 在使用者的電腦上建立cookies以用於在將來的訪問中儲存和檢索資料。
在開始之前,只要知道語言的幾個基本原則就行了:
1. 要在HTML檔案中把JavaScript程式碼封裝含進來的話,你必須要把代碼放在指令碼標籤(script)的內部,並加入text/javascript這一類型(type)屬性(清單1)。
2. 所有的JavaScript語句以分號結束。
3. 語言是大小寫敏感的。
4. 所有的變數名都必須以字母或是底線作為開始。
5. 你可以使用注釋來說明指令碼中的某些行,注釋的編寫方式是,以一個雙斜線(//)為開始,後面跟著注釋。
6. 你還可以使用注釋來把指令碼注釋掉。要注釋指令碼的多行的話,一種好的做法是使用/* 你的指令碼在這裡 */。任何位於星號之內的指令碼在執行過程中都不會運行。
清單1.需要使用script標籤和type屬性來把JavaScript程式碼封裝含到HTML檔案中來
<script type="text/javascript"></script>
<script type="text/javascript"></script>
要隱藏瀏覽器不支援的JavaScript的代碼,或是使用者想把代碼關掉的話,只要在JavaScrip語句的前後使用注釋標籤就可以了(清單2)。
清單2. 使用注釋來隱藏瀏覽器不支援的JavaScript代碼
<script type="text/javascript">
<!-- Example statement here //-->
</script>
<script type="text/javascript">
<!-- Example statement here //-->
</script>
最常用的把JavaScript程式碼封裝含到網頁中的方式是,使用指令碼(script)標籤中的src屬性來把代碼從一個外部的JavaScript檔案中載入進來(清單3)。
清單3. 在HTML檔案中包含外部的JavaScript檔案
<script type="text/javascript" src="path/to/javascript.js" kesrc="path/to/javascript.js"></script>
<script type="text/javascript" src="path/to/javascript.js" kesrc="path/to/javascript.js"></script>
外部JavaScript檔案是最常見的包含JavaScript代碼的方式,這是有一些很實在的原因的:
1. 如果你的HTML頁面中有著更少的代碼的話,搜尋引擎就能夠以更快的速度來抓取和索引你的網站。
2. 保持JavaScript代碼和HTML的分離,這樣代碼顯得更清晰,且最終更易於管理。
3. 因為可以在HTML代碼中包含進多個JavaScript檔案,因此你可以把JavaScript檔案分開放在web伺服器上不同的檔案目錄結構中,這類似於映像的存放方式,這是一種更容易管理代碼的做法。清晰、有條理的代碼始終是讓網站管理變得容易起來的關鍵。
變數
變數儲存資料,這些資料稍後要被檢索的或是要使用新的資料來更新。儲存在變數中的資料可以是一個值或運算式,JavaScript語言有三種類型的運算式,表1對此做了描述。
表1. JavaScript運算式
運算式描述
算術 計算的結果為一個數值
字串計算的結果為一個字串
邏輯 計算的結果為一個布爾值(true或者false)
變數有兩種類型:局部的和全域的。局部變數使用var這一關鍵字來聲明,聲明全域變數則不需要使用var關鍵字。使用了var關鍵字的變數被看成是 局部的,因為除了你聲明它的地方所處的範圍之外,它不能在其他任何地方被訪問。例如,如果你在一個函數(在將近文章的結尾部分我會談論到)的內部聲明了一個局部變數的話,該變數就不能在該函數之外被訪問,這就使得它是這一函數局部的。如果你沒有使用var關鍵字聲明這同一變數的話,它在整個指令碼中就都是可被訪問到的,而不僅限定於只能在那個函數中被訪問。
清單4給出了一個局部變數的例子,其被命名為num,並被賦值為10。
清單4. 聲明一個局部變數
var num = 10;
var num = 10;
要在指令碼中的另一個位置訪問num變數的值的話,你只需要通過名稱來引用該變數就可以了,如清單5所示。
清單5. 訪問變數的值
document.write("The value of num is: "+ num);
document.write("The value of num is: "+ num);
這一語句的結果是“The value of num is: 10”。這一document.write函數把資料寫到網頁中,在本文餘下的部分中你都是使用這一函數來把例子寫到網頁中。
要把算術運算式儲存到變數中的話,你只要把變數指配給計算的值就可以了,如清單6所示。計算的結果而非算式本身被儲存在變數中。因此,我們又一次得到這一結果“The value of num is: 10”。
清單6. 儲存算術運算式
var num = (5 + 5);
document.write("The value of num is: "+ num);
var num = (5 + 5);
document.write("The value of num is: "+ num);
要改變變數的值的話,通過你為變數所分配的名稱來引用變數,並使用等號來為其賦一個新的值(清單7)。這次的不同之處在於你不需要使用var關鍵字,因為變數已經聲明過了。
清單7. 改變現有變數的值
var num = 10;
document.write("The value of num is: "+ num); // 把num的值更新成15 num = 15;
document.write("The new value of num is: "+ num);
var num = 10;
document.write("The value of num is: "+ num); // 把num的值更新成15 num = 15;
document.write("The new value of num is: "+ num);
這一指令碼的結果先是一句“The value of num is: 10”,後面跟著“The new value of num is: 15”。除了講解變數之外,這一節內容還引入了下一個主題,也就是運算子。你用來把值賦給變數的等號(=)就是一個賦值運算子,以及你用在5+5中的加號(+)是一個算術運算子。下一節內容談論JavaScript語言中的所有變數運算子及其用法。
運算子
在執行JavaScript語言中的任何運算時,你都需要運算子。運算包括了加法、減法、比較等。JavaScript語言中有四種運算子。
1. 算術
2. 賦值
3. 比較
4. 邏輯
算術運算子
算術運算子執行基本的數學運算,比如說加減乘除等。表2列出並描述了JavaScript語言中的所有可用的算術運算。
表2. 算術運算子
運算子描述
+ 加法
- 減法
* 乘法
/ 除法
% 模數(找出餘數)
++ 遞增
--遞減
賦值運算子
算術運算子執行基本的數學運算,而賦值運算子則是把值賦給JavaScript變數。當你在前面一節中把值賦給變數時,你已經見到了最常用的賦值運算子。表3列出並描述了JavaScript語言中所有可用的賦值運算子。
表3. 賦值運算子
運算子描述
=等於
+=把加法值(變數加上值的結果值)賦給變數
-=把減法值(變數減去值的結果值)賦給變數
*=把乘法值(變數乘上值的結果值)賦給變數
/=把除法值(變數除以值的結果值)賦給變數
%=把模數值(變數對值模數的結果)賦給變數
你已經看到了如何使用等號來把值或是運算式賦給變數,但現在我會給展示如何使用一個令人稍加困惑的賦值運算子。把一個加法值賦給一個變數可能是一個很奇怪的概念,但實際上很簡單(清單8)。
清單8. 把一個加法值賦給一個變數
var num = 10;
document.write("The value of num is: "+ num); // 把num的值更新為15 num += 5;
document.write("The new value of num is: "+ num);
var num = 10;
document.write("The value of num is: "+ num); // 把num的值更新為15 num += 5;
document.write("The new value of num is: "+ num);
這一指令碼的結果是“The value of num is: 10”後面跟著“"The new value of num is: 15”。你可以看到,這一指令碼中的運算子把加法值賦給了變數。這也可以當作是清單9中所編寫的指令碼的一種簡短寫法。
清單9. 把加法值賦給變數的一種更長的寫法。
var num = 10;
document.write("The value of num is: "+ num); // 把num的值更新為15 num = (num + 5);
document.write("The new value of num is: "+ num);
var num = 10;
document.write("The value of num is: "+ num); // 把num的值更新為15 num = (num + 5);
document.write("The new value of num is: "+ num);
比較子
比較子確定變數或是它們的值之間的關係。你在條件陳述式中使用比較子,通過比較變數或是它們的值來計算出語句為true還是為false,以此建立邏輯。表4列出並描述了JavaScrpit語言中所有可用的比較子。
表4. 比較子
運算子描述
==等於
=== 全等,用於值和物件類型
!=不等於
>大於
<小於
>= 大於或等於
<= 小於或等於
在編寫任何類型的邏輯時,變數和值的比較都是最基本的。清單10中的例子展示了如何使用等於這一比較子(==)來確定10是否等於1。
清單10. 使用比較子
document.write(10 == 1);
document.write(10 == 1);
邏輯運算子
邏輯運算子通常是用來組合條件陳述式中的比較子。表5列出並描述了JavaScript語言中的所有可用的邏輯運算子。
表5. 邏輯運算子
運算子描述
&&與
||或
! 非
現在在變數和運算子方面你已經有些經驗了,是時候瞭解如何建立一種比簡單的變數有著更多儲存內容的機制了。
數組
數組類似於變數,但不同之處在於它們可以把多個值和運算式放在一個名稱之下。把多個值存放在一個變數中,這種做法造就了數組的強大。你可存放在 JavaScript數組中的資料的類型和數量都沒有限制,在指令碼中聲明數組之後,你就可以隨時訪問數組中的任何項的任何資料。雖然數組可以儲存 JavaScript語言的任何資料類型,包括其他數組,但最常見的做法是,把相類似的資料存放區在同一個數組中,並給它指定一個與數組項有關聯意思的名稱。清單11提供的例子使用了兩個獨立的數組來各自存放相類似的資料。
清單11. 把相類似的值存放在數組中
var colors = new Array("orange", "blue", "red", "brown");
var shapes = new Array("circle", "square", "triangle", "pentagon");
var colors = new Array("orange", "blue", "red", "brown");
var shapes = new Array("circle", "square", "triangle", "pentagon");
正如你見到的那樣,是可以把所有的這些資料項目都儲存在一個數組中,但這是不符合邏輯的,且有可能會在以後給指令碼帶來問題,比如說在識別數組中存放的是什麼資料時。
訪問數組中的值很容易,但這裡有一個陷阱存在。數組的ID總是從0而不是從1開始的,在第一次使用的時候你可能會有些困惑。ID從0開始遞增,例如0、1、2、3等。要訪問數組項的話你就必須要使用它的ID,其指向子項在數組中的位置(清單12)。
清單12. 把相類似的值儲存在一個數組中
var colors = new Array("orange", "blue", "red", "brown");
document.write("Orange: "+ colors[0]);
document.write("Blue: "+ colors[1]);
document.write("Red: "+ colors[2]);
document.write("Brown: "+ colors[3]);
var colors = new Array("orange", "blue", "red", "brown");
document.write("Orange: "+ colors[0]);
document.write("Blue: "+ colors[1]);
document.write("Red: "+ colors[2]);
document.write("Brown: "+ colors[3]);
也可以給數組中的某個位置賦值,或是更新數組中的某項的值,就像前面訪問數組中的項的做法一樣(清單13)。
清單13. 給數組中的特定位置賦值
var colors = new Array();
colors[0] = "orange";
colors[1] = "blue";
colors[2] = "red";
colors[3] = "brown";
document.write("Blue: "+ colors[1]); // 把blue更新成purple colors[1] = "purple";
document.write("Purple: "+ colors[1]);
var colors = new Array();
colors[0] = "orange";
colors[1] = "blue";
colors[2] = "red";
colors[3] = "brown";
document.write("Blue: "+ colors[1]); // 把blue更新成purple colors[1] = "purple";
document.write("Purple: "+ colors[1]);
現在你已經很好地瞭解了變數、運算子和數組,接下來把你所學的東西運用到實踐中,開始建立一些邏輯。
條件陳述式
條件陳述式是建立指令碼語言或是程式設計語言中各種類型的邏輯的骨架,JavaScript語言也不例外。條件陳述式基於你所寫的條件來確定要採取的行為,JavaScript語言有四種編寫條件陳述式的方式,表6對此做了描述。
表6. 條件陳述式
語句描述
if如果某個特定條件為true的話就執行指令碼
if...else 如果某個特定條件為true的話就執行某個指令碼,
如果條件為false的話則執行令一個指令碼
if...else if...else 如果不限個數的多個條件中之一為true的話就執行某個指令碼,
如果所有的條件都為false的話 就執行其他的指令碼
switch 執行許多指令碼中的一個
如果你只想在某個條件為true時執行某個指令碼的話,就使用if語句。清單14展示了如何使用帶有比較子的if語句來在條件為true時執行指令碼。
清單14. 使用if語句
var num = 10;
if(num == 5) {
document.write("num is equal to 5");
}
var num = 10;
if(num == 5) {
document.write("num is equal to 5");
}
如果你打算在某個條件為true時執行一個指令碼,而在條件為false時執行另一個指令碼話,那麼使用if...else語句,如清單15所示。
清單15. 使用if...else語句
var num = 10;
if(num == 5) {
document.write("num is equal to 5"); }
else {
document.write("num is NOT equal to 5, num is: "+ num);
}
var num = 10;
if(num == 5) {
document.write("num is equal to 5"); }
else {
document.write("num is NOT equal to 5, num is: "+ num);
}
如果要基於不同的條件來執行不同的指令碼的話,則使用if...else if...else語句,如清單16所示。
清單16. 使用if...else if...else語句
var num = 10;
if(num == 5) {
document.write("num is equal to 5");
} else if(num == 10) {
document.write("num is equal to 10");
}
else {
document.write("num is: "+ num);
}
var num = 10;
if(num == 5) {
document.write("num is equal to 5");
} else if(num == 10) {
document.write("num is equal to 10");
}
else {
document.write("num is: "+ num);
}
Swith語句不同於if語句,它們不能用來確定變數值是否大於或是小於另一個值。清單17給出的例子說明了使用switch語句來確定要執行的指令碼的適當時機。
清單17. 使用switch語句
var num = 10;
switch(num) {
case 5:
document.write("num is equal to 5");
break;
case 10:
document.write("num is equal to 10");
break;
default:
document.write("num is: "+ num);
}
var num = 10;
switch(num) {
case 5:
document.write("num is equal to 5");
break;
case 10:
document.write("num is equal to 10");
break;
default:
document.write("num is: "+ num);
}
你可能已經注意到清單17用到了case子句、break語句和default子句。這些子句和語句對switch語句來說都是很重要的部分。case子句確定了switch的值是否與子句中用到的資料值相等;break語句中斷——或是停止——switch語句執行語句的餘下部分;而default子句則標明了在沒有case語句執行的情況下或是已執行的case語句沒有break語句的情況下,預設要啟動並執行指令碼。例如,清單18說明了在已執行的case語句中如果沒有break語句的話,多個case語句和default語句是如何執行的。
清單18. 通過不包含break的方式來執行多行代碼
var num = 10;
switch(num) {
case 5:
document.write("num is equal to 5");
break;
case 10:
document.write("num is equal to 10");
default:
document.write("num is: "+ num);
}
var num = 10;
switch(num) {
case 5:
document.write("num is equal to 5");
break;
case 10:
document.write("num is equal to 10");
default:
document.write("num is: "+ num);
}
這一指令碼的結果先是一句“num is equal to 10”,後面再跟著一句“num is: 10”。這種情況有時被稱為switch直落。
正如本節開頭提到的那樣,條件陳述式是任何指令碼語言或是程式設計語言中的所有邏輯的骨架,不過如果不用函數的話,你得到的代碼就會像糾纏不清的一團亂麻。
函數
有許多理由可用來證明函數是很有用的。函數是那些只能由事件或是函數調用來執行的指令碼的容器,因此,在瀏覽器最初載入和執行包含在網頁中的指令碼的時候,函數並沒有被執行。函數的目的是包含那些要完成某個任務的指令碼,這樣你就隨時都能夠執行該指令碼和運行該任務。
構建一個函數很容易,其以function這一關鍵字作為開始,接著是一個空格,然後是函數的名稱。你可以選擇任何的字串來作為函數的名稱,不過讓函數的名稱和其要執行任務之間有某種關聯意思是很重要的。清單19給出了一個函數例子,該函數修改一個現有變數的值。
清單19. 構建一個簡單的函數
var num = 10;
function changeVariableValue() { num = 11;
}
changeVariableValue();
document.write("num is: "+ num);
var num = 10;
function changeVariableValue() { num = 11;
}
changeVariableValue();
document.write("num is: "+ num);
清單19中的例子不僅說明了如何構建一個函數,還說明了如何調用函數來修改變數的值。在這一例子中你能夠修改變數的值是因為,變數是在主指令碼範圍裡做聲明的,函數也是一樣,因此函數知道變數的存在。然而,如果變數是在函數的內部做聲明的話,那麼在函數的外部你是不能訪問該變數的。
函數還能夠通過函數的參數來接受資料,函數可以有一個或多個形式參數,函數調用基於函數的形式參數個數可以有一個或多個實際參數。形式參數(形參,parameter)和實際參數(實參,argument)常會被弄混;形參是函數定義的組成部分,而實參則是在調用函數時用到的運算式。清單20給出了一個函數例子,該函數帶有形參,函數調用則用到了實參。
清單20. 使用函數參數
var num = 10;
function increase(_num) {
_num++;
}
increase(num);
document.write("num is: "+ num);
var num = 10;
function increase(_num) {
_num++;
}
increase(num);
document.write("num is: "+ num);
這一例子中的函數遞增了任何傳遞給它的實際參數的值,該例中的實際參數是一個你已預先聲明了的變數。通過把它作為一個實際參數傳遞給函數,你把它的值遞增成了11。
return語句在函數中也是常被用到的,它們在執行完函數中的指令碼後返回一個值。例如,你可以把函數返回的值賦給一個變數。清單21中的例子說明了在執行指令碼之後,如何從函數中返回一個值。
清單21. 在函數中使用return語句
function add(_num1, _num2) {
return _num1+_num2;
}
var num = add(10, 10);
document.write("num is: "+ num);
function add(_num1, _num2) {
return _num1+_num2;
}
var num = add(10, 10);
document.write("num is: "+ num);
這一指令碼的結果是“num is: 20”。這一函數的好處是,它可以把你傳遞給它的任意兩個數字相加並返回相加後的值,你可以把該值賦給任何變數,而不是像清單20那樣總是改變同一個變數的值。
迴圈
正如你已經見到的那樣,數組是儲存大量可重用資料的一種很棒的方式。但這不過是一個開始;for和while迴圈提供了遍曆這些數組、訪問它們的值和使用它們來執行指令碼的功能。
JavaScript語言中最常用到的迴圈類型是for迴圈。for迴圈通常是這樣構成的,先是一個賦了數值的變數,然後該變數使用一個比較子來和另一個值做比較,最後該數字值被遞增或是遞減。for迴圈中的比較通常是確定初始變數的數值是否小於或是大於另一個數值,接著在條件為true的這段時間內,迴圈運行,變數遞增或是遞減直到條件的計算結果為false。清單22給出的例子說明了如何編寫一個for迴圈,當數值小於數組的長度時迴圈運行。
清單22. 構建一個for迴圈並遍曆一個數組
var colors = new Array("orange", "blue", "red", "brown");
for(var i=0; i {
document.write("The color is: "+ colors[i] +" ");
}
var colors = new Array("orange", "blue", "red", "brown");
for(var i=0; i {
document.write("The color is: "+ colors[i] +" ");
}
數組的length屬性提供了一個與數組中的子項個數相等的數值,再一次說明,這裡容易讓你出錯的一點是,數組的ID是從0開始的,因此,如果數組中有4個子項的話,長度就是4,但數組中的索引則是0、1、2和3——沒有4。
另一種迴圈類型是while迴圈,它們的執行速度比for迴圈快,但適用在一些不是遍曆數組的情況中,比如說當某個條件為true時執行某個指令碼。清單23展示了如何編寫這樣的一個while迴圈,即當數值變數小於10時執行某個指令碼。
清單23. 構建while迴圈
var i = 0;
while(i<10) {
document.write(i +" "); i++;
}
var i = 0;
while(i<10) {
document.write(i +" "); i++;
}
可以注意到,while迴圈中的指令碼包含了一行代碼,該行代碼疊加數值變數直到while迴圈中的條件為false為止。沒有這行代碼的話,你得到的就是一個無限迴圈。
結論
JavaScript語言可以說是最受歡迎的語言之一,現在你明白這是為什麼了。這一簡單而又豐富的指令碼語言帶來了如此之多的可能性,它提供的工具允許網站訪問者和下載後的網頁進行互動,這一功能非常的強大。本文為理解JavaScript語言的基本原理奠定了基礎,現在對你來說,要瞭解JavaScript庫函數的作用方式,以及如何使用它們來簡化網頁用戶端邏輯的編寫過程都應該是更容易的事了。接下來要做到事情就是把這些概念付諸實踐,並開始探索JavaScript對象。
摘自 塗劍凱的專欄