概要
64學(xué)時(shí) 3.5學(xué)分
章節(jié)安排
- 電子商務(wù)網(wǎng)站概況
- HTML5+CSS3
- JavaScript
- Node
電子商務(wù)網(wǎng)站概述
電子商務(wù)網(wǎng)站定義
電子商務(wù)網(wǎng)站是指一個(gè)企業(yè)、機(jī)構(gòu)或公司在互聯(lián)網(wǎng)上建立的站點(diǎn),其目的是為了宣傳企業(yè)形象这吻、發(fā)布產(chǎn)品信息宵膨、宣傳經(jīng)濟(jì)法規(guī)运杭、提供商業(yè)服務(wù)等蛹头。
電子商務(wù)網(wǎng)站功能
企業(yè)形象宣傳
新聞發(fā)布院塞、供求信息發(fā)布
產(chǎn)品和服務(wù)項(xiàng)目展示
商品和服務(wù)定購
電子商務(wù)網(wǎng)站的架構(gòu)
電子商務(wù)網(wǎng)站的構(gòu)成要素
- 網(wǎng)站域名
- 網(wǎng)站物理地點(diǎn)
- 網(wǎng)站頁面
- 商品目錄
- 購物車
- 付款臺(tái)
JavaScript
基礎(chǔ)語法
客戶端JavaScript
基礎(chǔ)語法
詞法結(jié)構(gòu)
類型遮晚、變量、運(yùn)算符和表達(dá)式
語句
數(shù)組
函數(shù)
對象
類和模塊
正則表達(dá)式的模式匹配
詞法結(jié)構(gòu)
JavaScript是區(qū)分大小寫的語言拦止。
JavaScript支持2種格式的注釋:
//這里是單行注釋
/*這里是一段注釋(這里的注釋可以連寫多行)*/
JavaScript中县遣,標(biāo)識(shí)符用來對變量和函數(shù)進(jìn)行命名。標(biāo)識(shí)符必須以字母汹族、下劃線(_
)或美元符($
)開始艺玲。后續(xù)的字符可以是字母、數(shù)字鞠抑、下劃線或美元符。
JavaScript保留字不能作為標(biāo)記符忌警,例如:break
搁拙、delete
、function
法绵、return
箕速、typeof
、case
朋譬、do
盐茎、if
、switch
徙赢、var
字柠、catch
。
JavaScript使用分號(hào)(;
)將語句分隔開狡赐。
類型窑业、變量、運(yùn)算符和表達(dá)式
JavaScript的數(shù)據(jù)類型分為2類:
- 原始類型:包括數(shù)字枕屉、字符串和布爾值常柄。JavaScript中有兩個(gè)特殊的原始值:
null
(空)和undefined
(未定義)。 - 對象類型:是屬性的集合搀擂,每個(gè)屬性都由“名/值對”構(gòu)成西潘。
數(shù)字、算術(shù)運(yùn)算符
數(shù)字:包括整數(shù)哨颂、浮點(diǎn)數(shù)喷市。
算術(shù)運(yùn)算符:加(+
)、減(-
)咆蒿、乘(*
)东抹、除(/
)蚂子、求余數(shù)(%
)棺禾、遞增(++
)卡睦、遞減(--
)、按位異或(^
)稀颁。
-
注意:
++
和--
運(yùn)算符的返回值依賴于它相對于操作數(shù)的位置馏谨。當(dāng)運(yùn)算符在操作數(shù)之前别渔,稱為“前增量”運(yùn)算符,它對操作數(shù)進(jìn)行增量計(jì)算惧互,并返回計(jì)算后的值哎媚。當(dāng)運(yùn)算符在操作數(shù)之后,稱為“后增量”運(yùn)算符喊儡,它對操作數(shù)進(jìn)行增量計(jì)算拨与,但返回未做增量計(jì)算的值。var i=1,j=++i; //i和j的值都是2 var i=1,j=i++; //i是2艾猜,j是1
^
如果不是出現(xiàn)在正則表達(dá)式中买喧,那么其代表按位異或運(yùn)算符,也可以充當(dāng)二進(jìn)制算法匆赃。-
異或的算法為相同輸出
0
淤毛,不同輸出1
。a^b a的二進(jìn)制 b的二進(jìn)制 運(yùn)算結(jié)果二進(jìn)制 運(yùn)算結(jié)果十進(jìn)制 6^8
0110
(三位算柳,不夠前面加0)1000
1110
14
20^31
10100
11111
01011
11
數(shù)學(xué)常量
常量 | 說明 |
---|---|
Math.E |
常量e低淡,自然對數(shù)的底數(shù) |
Math.LN10 |
10的自然對數(shù) |
Math.LN2 |
2的自然對數(shù) |
Math.LOG10E |
e以10為底的對數(shù) |
Math.LOG2E |
e以2為底的對數(shù) |
Math.PI |
常量π |
Math.SQRT1_2 |
2的平方根的倒數(shù) |
Math.SQRT2 |
2的平方根 |
數(shù)學(xué)函數(shù)
函數(shù) | 說明 | 函數(shù) | 說明 |
---|---|---|---|
Math.abs(x) |
返回x 的絕對值 |
Math.acos(x) |
返回x 的反余弦值 |
Math.asin(x) |
返回x 的反正弦值 |
Math.atan(x) |
返回x 的反正切值 |
Math.atan2(y,x) |
返回從X軸到指定點(diǎn)的角度,y 為點(diǎn)的Y坐標(biāo),x 為點(diǎn)的X坐標(biāo) |
Math.ceil(x) |
返回大于或等于x 的最接近的整數(shù) |
Math.cos(x) |
返回x 的余弦值 |
Math.exp(x) |
返回e的x 次方 |
Math.floor(x) |
返回小于或等于x 的最接近的整數(shù) |
Math.log(x) |
返回x 的自然對數(shù) |
Math.max(args…) |
返回參數(shù)中最大的值瞬项,參數(shù)中可以有多個(gè)值 | Math.min(args…) |
返回參數(shù)中最小的值蔗蹋,參數(shù)中可以有多個(gè)值 |
Math.pow(x,y) |
返回x 的y 次方 |
Math.random() |
返回一個(gè)在[0.0,1)之間的隨機(jī)數(shù) |
Math.round(x) |
返回最接近x 的整數(shù) |
Math.sin(x) |
返回x 的正弦值 |
Math.sqrt(x) |
返回x 的平方根 |
Math.tan(x) |
返回x 的正切值 |
數(shù)字相關(guān)方法
方法 | 說明 |
---|---|
n.toExponential(digits) |
返回以指數(shù)記數(shù)法表示的n 的字符串格式,小數(shù)點(diǎn)前有一個(gè)數(shù)字囱淋,小數(shù)點(diǎn)后有digits 個(gè)數(shù)字 |
n.toFixed(digits) |
返回n 的字符串格式纸颜,不使用指數(shù)記數(shù)法,在小數(shù)點(diǎn)后有指定的digits 個(gè)數(shù)字 |
n.toLocaleString() |
將n 轉(zhuǎn)換為本地格式的字符串 |
n.toPrecision(prec) |
返回一個(gè)包含prec 位有效數(shù)字的數(shù)字字符串绎橘,如果prec 足夠大胁孙,包括當(dāng)前數(shù)字的所有整數(shù)部分,則返回值與toFixed 方法一致称鳞。其他情況下涮较,將使用指數(shù)記數(shù)法,小數(shù)點(diǎn)前有一個(gè)數(shù)字冈止,小數(shù)點(diǎn)后有prec-1 個(gè)數(shù)字 |
n.toString() |
將n 轉(zhuǎn)換為字符串 |
Number(object) |
把對象的值轉(zhuǎn)換為數(shù)字狂票。如果參數(shù)是Date 對象,Number() 返回從1970年1月1日至今的毫秒數(shù)熙暴。如果對象的值無法轉(zhuǎn)換為數(shù)字闺属,那么Number() 函數(shù)返回NaN 慌盯。 |
字符串
由單引號(hào)或雙引號(hào)括起來的字符序列。由單引號(hào)定界的字符串中可以包含雙引號(hào)掂器,由雙引號(hào)定界的字符串中也可以包含單引號(hào)亚皂。
- 注意:當(dāng)使用單引號(hào)來定界字符串時(shí),需注意英文中的縮寫(can't)国瓮。因?yàn)槠蔡?hào)和單引號(hào)是同一個(gè)字符灭必,所以必須使用轉(zhuǎn)義字符(
\
)來轉(zhuǎn)義,例如'can\'t'
JavaScript的內(nèi)置功能之一就是字符串的連接乃摹。連接運(yùn)算符為“+
”禁漓。例如:
var msg="hello, "+"world"; //生成字符串“hello, world”
length
屬性可以確定一個(gè)字符串的長度,例如:msg.length
JavaScript中用“>
”或“<
”操作符比較字符串大小時(shí)孵睬,它們只會(huì)比較這些字符的Unicode編碼播歼,而不考慮本地的順序。
字符串類型的大小判斷是一個(gè)字符和一個(gè)字符的比較掰读,只要有字符不同就停止繼續(xù)判斷并返回比較結(jié)果荚恶。例如:"aBc"
<"ab"
;
localeCompare
方法可以實(shí)現(xiàn)漢字按拼音排序。
字符集 | 范圍 | Unicode編碼(16進(jìn)制) | Unicode編碼(10進(jìn)制) |
---|---|---|---|
數(shù)字 |
0 ~9
|
30 ~39
|
48 ~57
|
大寫字母 |
A ~Z
|
41 ~5A
|
65 ~90
|
小寫字母 |
a ~z
|
61 ~7A
|
97 ~122
|
基本漢字 |
一 ~龥
|
4E00 ~9FA5
|
19968 ~40869
|
字符串相關(guān)方法
方法 | 說明 | 方法 | 說明 |
---|---|---|---|
s.charAt(n) |
返回字符串s 的第n 個(gè)字符磷支,從0開始 |
s.concat(value,…) |
返回由每個(gè)參數(shù)連接為s而組成的新的字符串。 s="hello"; s.concat("","world","!");
|
s.indexOf(s1 [,start]) |
返回在s 中start 位置之后食寡,s1 第一次出現(xiàn)的位置雾狈,如果沒有找到則返回-1
|
s.lastIndexOf(s1[,start]) |
返回s1 在字符串s 的start 位置之前最后一次出現(xiàn)的位置,如果沒有找到則返回-1 抵皱。其從s 的結(jié)尾開始搜索到開頭 |
s.trim() |
去掉開頭和結(jié)尾處的空白字符 | s.match(s1) |
在字符串內(nèi)檢索指定的值,若找到善榛,則返回s1 ,若沒有找到呻畸,則返回null
|
s.replace(s1,s2) |
用于在s 中用s2 替換s1
|
s.search(s1) | 返回第一個(gè)s1 相匹配的子串的起始位置移盆。如果沒有找到任何匹配的子串,則返回 -1 伤为。 |
s.slice(start,end) |
返回從start 位置開始咒循,直到但不包含end 位置的所有字符 |
s.split(delimiter) |
通過delimiter 將s 切分成一個(gè)數(shù)組。 |
s.substr(start,length) |
返回從start 位置開始的length 個(gè)字符 |
s.substring(start,end) |
返回從start 位置開始绞愚,直到但不包含end 位置的所有字符 |
s.toLocaleLowerCase() |
以本地化的方式將s 轉(zhuǎn)為小寫 |
s.toLocaleUpperCase() |
以本地化的方式將s 轉(zhuǎn)為大寫 |
s.toLowerCase() |
將s 轉(zhuǎn)為小寫 |
s.toUpperCase() |
將s 轉(zhuǎn)為大寫 |
s.localeCompare(s1[,locale]) |
若s 比s1 小叙甸,返回一個(gè)小于0的數(shù),若s 比s1 大位衩,返回一個(gè)大于0的數(shù)裆蒸,若相同,返回0 糖驴×诺唬可用于漢字按拼音排序的規(guī)則佛致,例如"張三" >"李四" 。注意:Chrome瀏覽器在使用時(shí)需用: s.localeCompare(s1,"zh") 辙谜。locale 包含一種或多種語言或區(qū)域設(shè)置標(biāo)記的區(qū)域設(shè)置字符串?dāng)?shù)組俺榆。如果包含多個(gè)區(qū)域設(shè)置字符串,請以降序優(yōu)先級(jí)對它們進(jìn)行排列筷弦,確保首個(gè)條目為首選區(qū)域位置肋演。如果省略此參數(shù),則使用JavaScript運(yùn)行時(shí)的默認(rèn)區(qū)域設(shè)置烂琴。 |
布爾值爹殊、邏輯運(yùn)算符、關(guān)系運(yùn)算符奸绷、null
梗夸、undefined
布爾值:這個(gè)類型只有兩個(gè)值,保留字true
和false
号醉。
邏輯運(yùn)算符:&&
(邏輯與)惨篱、||
(邏輯或)、!
(邏輯非)
關(guān)系運(yùn)算符:==
(等于)贼邓、<
(小于)曙蒸、>
(大于)、<=
(小于等于)线椰、>=
(大于等于)胞谈、!=
(不等于)
null
是JavaScript語言的關(guān)鍵字,表示一個(gè)特殊值憨愉,常用來描述“空值”烦绳。
undefined
是變量的一種取值,表明變量沒有初始化。如果函數(shù)沒有返回值了罪,則返回undefined
。
變量
在JavaScript中聪全,使用一個(gè)變量之前應(yīng)先聲明泊藕。變量是用關(guān)鍵字var
來聲明的,例如:
var i,j; //通過一個(gè)var聲明多個(gè)變量
var i=0,j=0; //可以將變量的初始賦值和變量聲明合寫在一起
變量的作用域:
全局變量:聲明在函數(shù)外部的變量
-
局部變量:聲明在函數(shù)內(nèi)部的變量难礼。函數(shù)內(nèi)聲明的所有變量在函數(shù)體內(nèi)始終是可見的娃圆。這意味著變量在聲明之前甚至已經(jīng)可見玫锋。JavaScript的這個(gè)特性被非正式地稱為聲明提前(hoisting),例如:
var scope="global"; function f() { console.log(scope); //輸出“undefined”讼呢,而不是“global” var scope="local"; //變量在這里賦初始值撩鹿,但變量本身在函數(shù)體內(nèi)任何地方均是有定義的 console.log(scope); //輸出“l(fā)ocal” }
賦值
賦值表達(dá)式:JavaScript使用“=
”運(yùn)算符來給變量或者屬性賦值。
帶操作的賦值運(yùn)算:
運(yùn)算符 | 示例 | 等價(jià)于 |
---|---|---|
+= |
a+=b |
a=a+b |
-= |
a-=b |
a=a-b |
*= |
a*=b |
a=a*b |
/= |
a/=b |
a=a/b |
%= |
a%=b |
a=a%b |
^= |
a^=b |
a=a^b |
語句
條件語句
通過判斷指定表達(dá)式的值來決定執(zhí)行還是跳過某些語句悦屏。JavaScript中基本的條件語句有2種:
-
if
語句节沦,其有兩種形式:// 1 if (條件) 語句1; [else 語句2;] //2 if (條件){ 語句塊1; } [else{ 語句塊2; }]
chap3-1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>chap3-1</title>
</head>
<body>
<form>
<span>The Grade:</span><input type="text" id="Grade">
</form>
<script>
document.getElementById("Grade").onkeydown=function (e) {
if(e.keyCode==13){
if(e.target.value>=60)
alert("成績及格");
else
alert("成績不及格");
}
}
</script>
</body>
</html>
-
switch
語句础爬,其形式為:switch (expression){ case e1: //如果expression==e1甫贯,則執(zhí)行語句塊1 語句塊1; break; //停止執(zhí)行switch語句 case e2: //如果expression==e2,則執(zhí)行語句塊2 語句塊2; break; case en: //如果expression==en幕帆,則執(zhí)行語句塊n 語句塊n; break; default: //如果所有的條件都不匹配获搏,則執(zhí)行語句塊n+1 語句塊n+1; break; }
chap3-2.html
<body><form><span>The Grade:</span><input type="text" id="Grade"></form> <script>document.getElementById("Grade").onkeydown=function (e) { if(e.keyCode==13){ var Grank=Math.floor(document.getElementById("Grade").value/10); switch (Grank){ case 10: alert("優(yōu)秀"); break; case 9: alert("優(yōu)秀"); break; case 8: alert("良好"); break; case 7: alert("中等"); break; case 6: alert("及格"); break; default: alert("不及格"); break; }}} </script></body>
循環(huán)語句
可以讓一部分代碼重復(fù)執(zhí)行。JavaScript中有4種循環(huán)語句:
-
while
語句// 1 while (條件) 語句; // 2 while (條件){ 語句塊; }
chap3-3.html
<body> <form> <span>階乘:</span><input type="text" id="jc"> </form> <script> var o=document.getElementById("jc"); o.onkeydown=function (e) { if(e.keyCode==13){ var m=n=o.value; var result=1; while(n>0){ result*=n; n=n-1; } alert(m+"!="+result); } } </script> </body> </html>
-
do
/while
語句// 1 do 語句; while(條件); // 2 do{ 語句塊; }while(條件);
chap3-4.html
<body> <form> <span>階乘:</span><input type="text" id="jc"> </form> <script> var o=document.getElementById("jc"); o.onkeydown=function (e) { if(e.keyCode==13){ var m=n=o.value; var result=1; do{ result*=n; n--; }while(n>0); alert(m+"!="+result); } } </script> </body>
-
for
語句for(initialize;test;increment){ statements; }
chap3-5.html
<body> <form> <span>階乘:</span><input type="text" id="jc"> </form> <script> var o=document.getElementById("jc"); o.onkeydown=function (e) { if(e.keyCode==13){ var m=o.value; var result=1; for(var i=1;i<=m;i++){ result*=i; } alert(m+"!="+result); } } </script> </body>
-
for
/in
語句for(variable in object){ statements; }
chap3-6.html
<script> var a="1,2,3,4,5"; var arr=a.split(","); var sum=0; for(var i in arr){ sum+=Number(arr[i]); } alert(a+"中值的和為:"+sum); </script>
跳轉(zhuǎn)語句
可以使得JavaScript的執(zhí)行從一個(gè)位置跳轉(zhuǎn)到另一個(gè)位置失乾。
-
break
語句是跳轉(zhuǎn)到循環(huán)或者其他語句的結(jié)束常熙。 -
continue
語句是終止本次循環(huán)的執(zhí)行并開始下一次循環(huán)的執(zhí)行。
chap3-7.html
<script>
var sumb=sumc=0;
for(var i=1;i<=100;i++){
sumb+=i;
if(i==50)
break;
}
for(var i=1;i<=100;i++){
if(i==50)
continue;
sumc+=i;
}
alert("break的結(jié)果:"+sumb+"\n"+"continue的結(jié)果:"+sumc);
</script>
標(biāo)簽語句
標(biāo)簽是由語句前的標(biāo)識(shí)符和冒號(hào)組成:identifier:statement
通過給語句定義標(biāo)簽碱茁,就可以在程序的任何地方通過標(biāo)簽名引用這條語句裸卫。break
和continue
是JavaScript中唯一可以使用語句標(biāo)簽的語句。
break|continue identifier;
mainloop: while(j<=100){
j++;
continue mainloop; //跳轉(zhuǎn)到下一次循環(huán)
}
alert("j的值為:"+j);
mainloop: while(j<=100){
j++;
break mainloop;
}
alert("j的值為:"+j); //break語句跳轉(zhuǎn)至此處
注意:不管continue
語句帶不帶標(biāo)簽纽竣,它只能在循環(huán)體內(nèi)使用墓贿。
return
語句
可以指定函數(shù)調(diào)用后的返回值。return expression;
function squre(x) {
return x*x;
}
document.writeln("2的平方等于:"+squre(2)+"<br>");
異常處理語句
所謂異常(exception)是當(dāng)發(fā)生了某種異常情況或錯(cuò)誤時(shí)產(chǎn)生的一個(gè)信號(hào)蜓氨。拋出異常就是用信號(hào)通知發(fā)生了錯(cuò)誤或異常情況聋袋。捕獲異常是指處理這個(gè)信號(hào),即采取必要的手段從異常中恢復(fù)穴吹。
throw
語句可以拋出異常:throw expression;
try
/catch
/finally
語句可以捕獲異常:
try{
//通常來講幽勒,這里的代碼會(huì)從頭執(zhí)行到尾而不會(huì)產(chǎn)生問題,但有時(shí)會(huì)拋出一個(gè)異常港令,要么是由throw語句直接拋出異常啥容,要么是通過調(diào)用一個(gè)方法間接拋出異常
}
catch(e){
//當(dāng)且僅當(dāng)try語句塊拋出了異常,才會(huì)執(zhí)行這里的代碼顷霹。這里可以通過局部變量e來獲得對Error對象或者拋出的其它值的引用咪惠,這里的代碼塊可以基于某種原因處理這個(gè)異常,也可以忽略這個(gè)異常淋淀,還可以通過throw語句重新拋出異常遥昧。
}
finally{
/*不管try語句塊是否拋出了異常,這里的邏輯總是會(huì)執(zhí)行,終止try語句塊的方式有:
1)正常終止渠鸽,執(zhí)行完語句塊的最后一條語句
2)通過break叫乌、continue或return語句終止
3)拋出一個(gè)異常,異常被catch從句捕獲
4)拋出一個(gè)異常徽缚,異常未被捕獲憨奸,繼續(xù)向上傳播
*/
}
chap3-8.html
<script>
function jc(x) {
if(x<0||x>10) throw new Error("x的值不能為負(fù)");
for(var res=1;x>1;res*=x,x--);
return res;
}
var grade=Number(prompt("請輸入一個(gè)正整數(shù):",""));
try{
alert(grade+"!="+jc(grade));
}
catch (e){
alert(e);
var grade=Number(prompt("請輸入一個(gè)正整數(shù):",""));
if(grade>10) throw new Error("x的值不能超過10");
alert(grade+"!="+jc(grade));
}
finally {
alert("x的范圍為1-10之間");
}
</script>
數(shù)組
數(shù)組是值的有序集合。每個(gè)值叫做一個(gè)元素凿试,而每個(gè)元素在數(shù)組中有一個(gè)位置排宰,以數(shù)字表示,稱為索引那婉。
JavaScript數(shù)組是無類型的:數(shù)組元素可以是任意類型板甘,并且同一個(gè)數(shù)組中的不同元素也可能有不同的類型。
創(chuàng)建
創(chuàng)建數(shù)組有2種方式:
-
數(shù)組直接量:
var empty=[]; //沒有元素的數(shù)組 var primes=[1,2,3,4,5]; //有5個(gè)數(shù)值的數(shù)組 var misc=[1.1,true,"a"]; //3個(gè)不同類型的元素 var base=1024; var table=[base,base+1,base+2]; //值可以是表達(dá)式 var b=[{x:1,y:2},primes]; //值還可以對象或其它數(shù)組
如果省略數(shù)組直接量中的某個(gè)值详炬,省略的元素將被賦予
undefined
值:var count=[1,,3]; //數(shù)組有3個(gè)元素盐类,中間的那個(gè)元素值為undefined var undefs=[,,]; //數(shù)組有2個(gè)元素,都是undefined
數(shù)組直接量的語法允許有可選的結(jié)尾的逗號(hào)呛谜,故
[,,]
只有兩個(gè)元素在跳,而非三個(gè)。 -
調(diào)用構(gòu)造函數(shù)
Array()
隐岛,其有2種形式:-
調(diào)用時(shí)沒有參數(shù):
var a=new Array();
該方法創(chuàng)建一個(gè)沒有任何元素的空數(shù)組猫妙,等同于數(shù)組直接量
[]
。 -
調(diào)用時(shí)有一個(gè)數(shù)值參數(shù)聚凹,它指定長度:
var a=new Array(10);
當(dāng)預(yù)先知道所需元素個(gè)數(shù)時(shí)割坠,這種形式的
Array()
構(gòu)造函數(shù)可以用來預(yù)分配一個(gè)數(shù)組空間。此時(shí)數(shù)組中沒有存儲(chǔ)值妒牙,甚至數(shù)組的索引屬性“0
”彼哼、“1
”等還未定義。我們可以用
new Array()
顯示指定兩個(gè)或多個(gè)數(shù)組元素或者數(shù)組的一個(gè)非數(shù)值元素:var a=new Array(5,4,"testing");
-
讀寫
數(shù)組元素的讀與寫:使用[]
操作符來訪問數(shù)組中的一個(gè)元素湘今。
var a=["hello"]; //從一個(gè)元素的數(shù)組開始
var value=a[0]; //讀第0個(gè)元素
a[1]=3.14; //寫第1個(gè)元素
i=2;
a[i]=3; //寫第2個(gè)元素
document.write(a.length);
JavaScript中數(shù)組的特別之處在于敢朱,當(dāng)使用小于232的非負(fù)整數(shù)作為索引時(shí),數(shù)組會(huì)自動(dòng)維護(hù)其length
屬性值象浑,如上蔫饰,創(chuàng)建僅有一個(gè)元素的數(shù)組愉豺,然后在索引1
和2
處分別進(jìn)行賦值褥蚯,則數(shù)組的長度變?yōu)?code>3挚冤。
注意:JavaScript中數(shù)組索引僅僅是對象屬性名的一種特殊類型,這意味著數(shù)組沒有“越界”錯(cuò)誤的概念赞庶。當(dāng)試圖查詢對象中不存在的屬性時(shí)仆嗦,不會(huì)報(bào)錯(cuò)钱贯,只會(huì)得到undefined
值。
稀疏數(shù)組
就是包含從0開始的不連續(xù)索引的數(shù)組。稀疏數(shù)組length
屬性大于元素的個(gè)數(shù)袭景。可以用Array()
構(gòu)造函數(shù)或簡單地指定數(shù)組的索引值大于當(dāng)前的數(shù)組長度來創(chuàng)建稀疏數(shù)組涡真。
a=new Array(5); //數(shù)組沒有元素篙贸,但是a.length是5
a[1000]=0; //賦值添加一個(gè)元素,但是設(shè)置length為1001
足夠稀疏的數(shù)組通常在實(shí)現(xiàn)上比稠密的數(shù)組更慢茅特,內(nèi)存利用率更高忘分,在這樣的數(shù)組中查找元素的時(shí)間更長。
元素的添加
數(shù)組元素的添加有3種方式:
-
為新索引賦值:
var a=[]; //開始是一個(gè)空數(shù)組 a[0]="zero"; //然后向其中添加元素 a[1]="one";
-
使用
push()
方法在數(shù)組末尾添加一個(gè)或多個(gè)元素:var a=[]; //開始是一個(gè)空數(shù)組 a.push("zero"); //在末尾添加一個(gè)元素 a.push("one","two"); //在末尾添加兩個(gè)元素
-
使用
unshift()
方法在數(shù)組頭部添加一個(gè)或多個(gè)元素:var a=[]; //開始是一個(gè)空數(shù)組 a.unshift("two"); //在頭部添加一個(gè)元素 a.unshift("zero","one"); //在頭部添加兩個(gè)元素
元素的刪除
數(shù)組元素的刪除有3種方式:
-
使用
delete
運(yùn)算符刪除:對一個(gè)數(shù)組使用
delete
不會(huì)修改數(shù)組的length
屬性白修,也不會(huì)將元素從高索引處移下來填充已刪除屬性留下的空白妒峦。var a=[1,2,3]; delete a[1]; //a在索引1的位置不再有元素
-
使用
pop()
方法刪除數(shù)組末尾的元素:該方法減少數(shù)組的長度。
var a=[1,2,3]; a.pop(); //刪除a尾部的元素
-
使用
shift()
方法在數(shù)組頭部刪除一個(gè)或多個(gè)元素:該方法減少數(shù)組的長度兵睛,并將所有隨后的元素下移一個(gè)位置來填補(bǔ)數(shù)組頭部的空缺肯骇。
var a=[1,2,3]; a.shift(); //刪除a頭部的元素
多維數(shù)組
JavaScript不支持真正的多維數(shù)組窥浪,但可以用數(shù)組的數(shù)組來近似。
chap3-9.html
<head><style>
span{display: inline-block;width: 80px;height: 60px;font-size: xx-large}</style>
</head>
<body>
<script>
var table=new Array(10); //表格有10行
for(var i=0;i<table.length;i++)
table[i]=new Array(10); //每行有10列
//初始化數(shù)組
for(var row=0;row<table.length;row++){
for(var col=0;col<table[row].length;col++){
table[row][col]=row*col;
}
}
//輸出數(shù)組元素值
for(var row=0;row<table.length;row++){
for(var col=0;col<table[row].length;col++){
document.write("<span>"+table[row][col]+"</span>");
}
document.write("<br>");
}
</script>
</body>
數(shù)組方法
join()
:將數(shù)組中所有元素都轉(zhuǎn)化為字符串并連接在一起笛丙,返回最后生成的字符串漾脂。可以指定一個(gè)可選的字符串在生成的字符串中來分隔數(shù)組的各個(gè)元素胚鸯。如果不指定分隔符骨稿,默認(rèn)使用逗號(hào)。
var a=[1,2,3]; //創(chuàng)建一個(gè)包含三個(gè)元素的數(shù)組
var str=a.join(); //str的值為“1姜钳,2啊终,3”
str=a.join(" "); //str的值為“1 2 3”
reverse()
:將數(shù)組中的元素顛倒順序,返回逆序的數(shù)組傲须。
var a=[1,2,3]; //創(chuàng)建一個(gè)包含三個(gè)元素的數(shù)組
a.reverse();
for(var i=0;i<a.length;document.write(a[i]+"<br>"),i++);
sort()
:將數(shù)組中的元素排序并返回排序后的數(shù)組蓝牲,語法為:arrayObject.sort([sortby])
-
如果調(diào)用該方法時(shí)沒有使用參數(shù),將按字母順序?qū)?shù)組中的元素進(jìn)行排序泰讽,說得更精確點(diǎn)例衍,是按照字符編碼的順序進(jìn)行排序。
var a=["banana","cherry","apple"]; a.sort(); for(var i=0;i<a.length;document.write(a[i]+"<br>"),i++); var b=[33,4,1111,222]; b.sort(); //輸出結(jié)果:1111 222 33 4 for(var i=0;i<b.length;document.write(b[i]+"<br>"),i++);
-
如果想按照其他標(biāo)準(zhǔn)進(jìn)行排序已卸,就需要提供比較函數(shù)(
sortby
)佛玄,該函數(shù)要比較兩個(gè)值,然后返回一個(gè)用于說明這兩個(gè)值的相對順序的數(shù)字累澡。比較函數(shù)應(yīng)該具有兩個(gè)參數(shù)a
和b
梦抢,其返回值如下:- 若
a
小于b
,在排序后的數(shù)組中a
應(yīng)該出現(xiàn)在b
之前愧哟,則返回一個(gè)小于0
的值奥吩。 - 若
a
等于b
,則返回0
蕊梧。 - 若
a
大于b
霞赫,則返回一個(gè)大于0
的值。
- 若
chap3-10.html
<script>
var a=["banana","cherry","apple"];
a.sort();
for(var i=0;i<a.length;document.write(a[i]+"<br>"),i++);
var b=[33,4,1111,222];
b.sort(); //輸出結(jié)果:1111 222 33 4
for(var i=0;i<b.length;document.write(b[i]+"<br>"),i++);
b.sort(function (m,n) {
return m-n; //按由小到大的順序排列
});
for(var i=0;i<b.length;document.write(b[i]+"<br>"),i++);
</script>
concat()
:創(chuàng)建并返回一個(gè)新數(shù)組肥矢,它的元素包括調(diào)用concat()
的原始數(shù)組的元素和concat()
的每個(gè)參數(shù)端衰。如果這些參數(shù)中的任何一個(gè)自身是數(shù)組,則連接的是數(shù)組的元素甘改,而非數(shù)組本身旅东。
注意:concat()
不會(huì)遞歸扁平化數(shù)組的數(shù)組。concat()
也不會(huì)修改調(diào)用的數(shù)組十艾。
chap3-11.html
<head>
<meta charset="UTF-8">
<title>chap3-11</title>
<style>
span{display: inline-block;width: 80px;height: 60px;font-size: xx-large}
span#s1{display: block}
</style>
</head>
<body>
<script>
var a=[1,2,3];
var b=a.concat(4,5); //返回[1,2,3,4,5]
b=a.concat([4,5],[6,7]); //返回[1,2,3,4,5,6,7]
b=a.concat([4,[5,[6,7]]]); //返回[1,2,3,4,[5,[6,7]]]
for(var i=0;i<b.length;i++){
if(Array.isArray(b[i]))
for(var j=0;j<b[i].length;document.write("<span>"+b[i][j]+"</span>"),j++);
else
document.write("<span id='s1'>"+b[i]+"</span>");
}
</script>
</body>
slice()
方法返回一個(gè)新的數(shù)組抵代,包含從start到end (不包括該元素)的arrayObject中的元素。其語法格式為:
arrayObject.slice(start,end)
-
start
:必需疟羹。規(guī)定從何處開始選取主守。如果是負(fù)數(shù),那么它規(guī)定從數(shù)組尾部開始算起的位置榄融。也就是說参淫,-1
指最后一個(gè)元素,-2
指倒數(shù)第二個(gè)元素愧杯,以此類推涎才。 -
end
:可選。規(guī)定從何處結(jié)束選取力九。該參數(shù)是數(shù)組片斷結(jié)束處的數(shù)組下標(biāo)耍铜。如果沒有指定該參數(shù),那么切分的數(shù)組包含從start
到數(shù)組結(jié)束的所有元素跌前。如果這個(gè)參數(shù)是負(fù)數(shù)棕兼,那么它規(guī)定的是從數(shù)組尾部開始算起的元素。
var a=[1,2,3,4,5];
document.write(a.slice(0,3)+"<br>"); //返回[1抵乓,2伴挚,3]
document.write(a.slice(3)+"<br>"); //返回[4,5]
document.write(a.slice(1,-1)+"<br>"); //返回[2灾炭,3茎芋,4]
splice()
方法向/從數(shù)組中添加/刪除項(xiàng)目,然后返回被刪除的項(xiàng)目蜈出。其語法格式為:
arrayObject.splice(index,howmany,item1,.....,itemX)
-
index
:必需田弥。整數(shù),規(guī)定添加/刪除項(xiàng)目的位置铡原,使用負(fù)數(shù)可從數(shù)組結(jié)尾處規(guī)定位置偷厦。 -
howmany
:必需。要?jiǎng)h除的項(xiàng)目數(shù)量燕刻。如果設(shè)置為0
沪哺,則不會(huì)刪除項(xiàng)目。 -
item1
,…,itemX
:可選酌儒。向數(shù)組添加的新項(xiàng)目辜妓。 -
splice()
方法可刪除從index
處開始的零個(gè)或多個(gè)元素,并且用參數(shù)列表中聲明的一個(gè)或多個(gè)值來替換那些被刪除的元素忌怎。 - 如果從
arrayObject
中刪除了元素籍滴,則返回的是含有被刪除的元素的數(shù)組。
chap3-12.html
<script>
var a=[1,2,3,4,5];
document.write(a.slice(0,3)+"<br>"); //返回[1榴啸,2孽惰,3]
document.write(a.slice(3)+"<br>"); //返回[4,5]
document.write(a.slice(1,-1)+"<br>"); //返回[2鸥印,3勋功,4]
a.splice(2,0,6);
document.write(a+"<br>"); //返回[1,2,6,3,4,5]
a.splice(2,1);
document.write(a+"<br>"); //返回[1,2,3,4,5]
a.splice(2,1,6);
document.write(a+"<br>"); //返回[1,2,6,4,5]
a.splice(2,3,3);
document.write(a+"<br>"); //返回[1,2,3]
a.splice(3,0,4,5);
document.write(a+"<br>"); //返回[1,2,3,4,5]
</script>
函數(shù)
函數(shù)是這樣的一段JavaScript代碼函筋,它只定義一次,但可能被執(zhí)行或調(diào)用任意次他匪。
JavaScript函數(shù)是參數(shù)化的:函數(shù)的定義會(huì)包括一個(gè)稱為形參(parameter)的標(biāo)識(shí)符列表劫狠,這些參數(shù)在函數(shù)體中像局部變量一樣工作。函數(shù)調(diào)用會(huì)為形參提供實(shí)參(argument)的值骚揍。函數(shù)使用它們實(shí)參的值來計(jì)算返回值字管,成為該函數(shù)調(diào)用表達(dá)式的值。
除了實(shí)參之外信不,每次調(diào)用還會(huì)擁有另一個(gè)值嘲叔,即本次調(diào)用的上下文(context),這就是this關(guān)鍵字的值抽活。如果函數(shù)掛載在一個(gè)對象上硫戈,作為對象的一個(gè)屬性,就稱它為對象的方法下硕。當(dāng)通過這個(gè)對象來調(diào)用函數(shù)時(shí)掏愁,該對象就是此次調(diào)用的上下文,也就是該函數(shù)的this
的值卵牍。
JavaScript的函數(shù)可以嵌套在其他函數(shù)中定義果港,這樣就構(gòu)成了一個(gè)閉包(closure)。
定義
函數(shù)使用function
關(guān)鍵字來定義糊昙,它可以用在:
-
函數(shù)聲明語句
在函數(shù)聲明語句中:
-
function
關(guān)鍵字后的函數(shù)名稱是函數(shù)聲明語句必需的部分辛掠。 - 一對圓括號(hào),其中包含由0個(gè)或者多個(gè)用逗號(hào)隔開的形參組成的列表释牺。
- 一對花括號(hào)萝衩,其中包含0條或多條JavaScript語句。
這些語句構(gòu)成了函數(shù)體没咙,一旦調(diào)用函數(shù)猩谊,就會(huì)執(zhí)行這些語句。
function jc(x) { var result=1; for(var i=1;i<=x;i++){ result*=i; } return result; } var a=Number(prompt("請輸入一個(gè)正整數(shù):","")); document.write(jc(a)+"<br>");
-
-
函數(shù)定義表達(dá)式
對于函數(shù)定義表達(dá)式來說祭刚,函數(shù)名稱是可選的牌捷,如果存在,該名字只存在于函數(shù)體中涡驮,并指代該函數(shù)對象本身暗甥。
var square=function(x) {return x*x;}; //定義時(shí)函數(shù)名稱省略 document.write(square(a)+"<br>"); //調(diào)用時(shí)使用變量名稱(實(shí)參)形式 var f=function fact(x) { //定義時(shí)可以包含函數(shù)名稱 if (x<=1) return 1; else return x*fact(x-1); } document.write(f(a)+"<br>"); //調(diào)用時(shí)使用變量名稱(實(shí)參)形式
如同變量,函數(shù)聲明語句“被提前”到外部腳本或外部函數(shù)作用域的頂部捉捅,所以以這種方式聲明的函數(shù)撤防,可以被在它定義之前出現(xiàn)的代碼所調(diào)用。
但是棒口,對于函數(shù)定義表達(dá)式而言寄月,就另當(dāng)別論了辜膝,為了調(diào)用一個(gè)函數(shù),必須要能引用它漾肮,而要使用一個(gè)以表達(dá)式方式定義的函數(shù)之前厂抖,必須把它賦值給一個(gè)變量。變量的聲明提前了初橘,但給變量賦值是不會(huì)提前的,所以充岛,以表達(dá)式方式定義的函數(shù)在定義之前無法調(diào)用保檐。
chap3-13.html
<script>
var a=Number(prompt("請輸入一個(gè)正整數(shù):",""));
document.write(jc(a)+"<br>");
function jc(x) {
var result=1;
for(var i=1;i<=x;i++){
result*=i;
}
return result;
}
var square=function(x) {return x*x;}; //定義時(shí)函數(shù)名稱省略
document.write(square(a)+"<br>"); //調(diào)用時(shí)使用變量名稱(實(shí)參)形式
var f=function fact(x) { //定義時(shí)可以包含函數(shù)名稱
if (x<=1)
return 1;
else
return x*fact(x-1);
}
document.write(f(a)+"<br>"); //調(diào)用時(shí)使用變量名稱(實(shí)參)形式
</script>
調(diào)用
有4種方式來調(diào)用JavaScript函數(shù):
作為函數(shù)調(diào)用:
var a=jc(10);
-
作為方法調(diào)用:
var b=Math.floor(3.2);
方法調(diào)用和函數(shù)調(diào)用有一個(gè)重要的區(qū)別,即:調(diào)用上下文崔梗。
this
關(guān)鍵字只能出現(xiàn)在函數(shù)中夜只,當(dāng)然在全局作用域中是個(gè)例外。全局作用域中
this
指向全局對象(全局對象在瀏覽器這個(gè)環(huán)境中指window
)蒜魄。如果
this
出現(xiàn)在函數(shù)中扔亥,其指向的依據(jù)就是函數(shù)的執(zhí)行環(huán)境而不是聲明環(huán)境。換句話說谈为,this
永遠(yuǎn)指向所在函數(shù)的所有者旅挤,當(dāng)沒有顯示的所有者的時(shí)候,那么this
指向全局對象伞鲫。各種情況下的
this
的具體指向:在全局作用域中
this
指向?yàn)槿謱ο?code>window粘茄。document.write(this+ "<br>");
-
函數(shù)作為某個(gè)對象的成員方法調(diào)用時(shí)
this
指向該對象。chap3-14.js
var name="zhangsan"; var obj={ name:"lizi", getName:function () { document.write(this.name + "<br>"); } } obj.getName(); //輸出lizi
-
函數(shù)作為函數(shù)直接使用時(shí)
this
指向全局對象秕脓。chap3-14.js
var name="zhangsan"; var obj={ name:"lizi", getName:function () { document.write(this.name + "<br>"); } } var nameGet=obj.getName; nameGet(); //輸出zhangsan
-
函數(shù)作為構(gòu)造函數(shù)調(diào)用時(shí)
this
指向用該構(gòu)造函數(shù)構(gòu)造出來的新對象柒瓣。chap3-14.js
var name="zhangsan"; var obj1=function (x,y) { this.name=x+y; } obj1.prototype.getName=function () { document.write(this.name + "<br>"); } var myObj=new obj1("wang","er"); myObj.getName(); //輸出wanger
-
call()
、apply()
和bind()
方法可以改變函數(shù)執(zhí)行時(shí)候的this
指向吠架。function Sister() { this.age=18; this.sayAge=function () {document.write("Age:"+this.age+ "<br>");} } function Brother() { this.age=25; this.sayAge=function () {document.write("Age:"+this.age+ "<br>");} } var sis=new Sister(); var bro=new Brother(); sis.sayAge.call(bro); //輸出"Age:25"
-
作為構(gòu)造函數(shù)調(diào)用
如果函數(shù)或者方法調(diào)用之前帶有關(guān)鍵字
new
芙贫,它就構(gòu)成構(gòu)造函數(shù)調(diào)用。var myObj=new obj1("wang","er");
構(gòu)造函數(shù)調(diào)用創(chuàng)建和初始化一個(gè)新的對象
myObj
傍药,并將這個(gè)對象用做其調(diào)用上下文磺平,因此構(gòu)造函數(shù)可以使用this
關(guān)鍵字來引用這個(gè)新創(chuàng)建的對象。myObj
對象繼承自構(gòu)造函數(shù)的prototype
屬性拐辽。 -
間接調(diào)用
call()
和apply()
方法可以看做是某個(gè)對象的方法褪秀,通過調(diào)用方法的形式來間接調(diào)用函數(shù)。他們的用途相同薛训,都是在特定的作用域中調(diào)用函數(shù)媒吗。
接收參數(shù)方面不同,
apply()
接收兩個(gè)參數(shù)乙埃,一個(gè)是函數(shù)運(yùn)行的作用域(this
)闸英,另一個(gè)是參數(shù)數(shù)組锯岖。call()
方法第一個(gè)參數(shù)與apply()
方法相同,但傳遞給函數(shù)的參數(shù)必須列舉出來甫何。chap3-14.js
window.firstName="San"; window.lastName="Zhang"; var myObject={firstName:"my",lastName:"Object"}; function HelloName() {document.write(this.firstName+" "+this.lastName+ "<br>");} HelloName.call(window); //輸出"San Zhang" HelloName.call(this); //輸出"San Zhang" HelloName.call(myObject); //輸出"my Object" function sum(m,n) { return m+n; } document.write(sum.call(window,10,10)+ "<br>"); //輸出20 document.write(sum.apply(window,[10,20])+ "<br>"); ////輸出30
實(shí)參和形參
JavaScript中的函數(shù)定義并未指定函數(shù)形參的類型出吹,函數(shù)調(diào)用也未對傳入的實(shí)參值做任何類型檢查。實(shí)際上辙喂,JavaScript函數(shù)調(diào)用甚至不檢查傳入形參的個(gè)數(shù)捶牢。
可選形參:當(dāng)調(diào)用函數(shù)的時(shí)候傳入的實(shí)參比形參個(gè)數(shù)少時(shí),剩下的形參都將設(shè)置為undefined
值巍耗。因此在調(diào)用函數(shù)時(shí)形參是否可選以及是否可以省略應(yīng)當(dāng)保持較好的適應(yīng)性秋麸。為了做到這一點(diǎn),應(yīng)當(dāng)給省略的參數(shù)賦一個(gè)合理的默認(rèn)值炬太。
- 注意:當(dāng)用這種可選形參來實(shí)現(xiàn)函數(shù)時(shí)灸蟆,需要將可選形參放在形參列表的最后。
chap3-15.js
function int(x,type) {
if(type===undefined) return Math.floor(x);
if(type===1) return Math.floor(x);
if(type===2) return Math.ceil(x);
if(type===3) return Math.round(x);
}
document.write("3.4默認(rèn)去尾法取整:" +int(3.4)+"<br>");
document.write("3.4去尾法取整:" +int(3.4,1)+"<br>");
document.write("3.4進(jìn)位法取整:" +int(3.4,2)+"<br>");
document.write("3.4四舍五入取整:" +int(3.4,3)+"<br>");
可變長的實(shí)參列表(實(shí)參對象):當(dāng)調(diào)用函數(shù)的時(shí)候傳入的實(shí)參個(gè)數(shù)超過函數(shù)定義時(shí)的形參個(gè)數(shù)時(shí)亲族,沒有辦法直接獲得未命名值的引用炒考。參數(shù)對象解決了這個(gè)問題。
- 實(shí)參對象有一個(gè)重要的用處就是:讓函數(shù)可以操作任意數(shù)量的實(shí)參霎迫。
- 假設(shè)定義了函數(shù)
f
斋枢,它的形參只有一個(gè)x
驱闷。如果調(diào)用f
時(shí)傳入兩個(gè)實(shí)參者娱,第一個(gè)實(shí)參可以通過形參名x
來獲得琉历,也可以通過arguments[0]
來得到糕非;第二個(gè)實(shí)參只能通過arguments[1]
來得到役衡。此外咙轩,和數(shù)組一樣眶明,arguments.length
屬性返回實(shí)參的個(gè)數(shù)惩坑。 - 注意:
arguments
不是數(shù)組谒主,它是一個(gè)實(shí)參對象朝扼。每個(gè)實(shí)參對象都包含以數(shù)字為索引的一組元素以及length
屬性。
chap3-15.js
function max() {
var max=Number.NEGATIVE_INFINITY; //NEGATIVE_INFINITY 表示負(fù)無窮大
for(var i=0;i<arguments.length;i++){
if(arguments[i]>max) max=arguments[i];
}
return max;
}
var largest=max(1,10,100,2,3,1000,4,5,10000,6);
document.write("最大值為:"+largest+"<br>");
將對象屬性用做實(shí)參:當(dāng)一個(gè)函數(shù)包含超過三個(gè)形參時(shí)霎肯,對于程序員來說擎颖,要記住調(diào)用函數(shù)中實(shí)參的正確順序很難。最好通過名/值對的形式來傳入?yún)?shù)观游,這樣參數(shù)的順序就無關(guān)緊要了搂捧。為了實(shí)現(xiàn)這種風(fēng)格的方法調(diào)用,定義函數(shù)時(shí)懂缕,傳入的實(shí)參都寫入一個(gè)單獨(dú)的對象中允跑,在調(diào)用的時(shí)候傳入一個(gè)對象,對象中的名/值對是真正需要的實(shí)參數(shù)據(jù)。
chap3-15.js
function arraycopy(from,from_start,to,to_start,length) {
for(var i=to_start;i<to_start+length;i++){
to[i]=from[from_start+i-to_start];
}
}
function easycopy(args) {
arraycopy(args.from,
args.from_start||0, //這里設(shè)置了默認(rèn)值
args.to,
args.to_start||0, //這里設(shè)置了默認(rèn)值
args.length
);
}
var a=[1,2,3,4],b=[5,6,7,8];
easycopy({from:a, to:b, to_start:2, length:4});
for(var i=0;i<b.length;i++){document.write(b[i]+"<br>");}
作為值的函數(shù)
在JavaScript中聋丝,函數(shù)不僅是一種語法索烹,也是值,也就是說弱睦,可以將函數(shù)賦值給變量百姓。
chap3-16.js
function squre(x) {return x*x;}
var s=squre; //現(xiàn)在s和squre指代同一個(gè)函數(shù)
document.write(squre(4)+"<br>");
document.write(s(4)+"<br>");
除了可以將函數(shù)賦值給變量,同樣可以將函數(shù)賦值給對象的屬性况木。
chap3-16.js
var o={square:squre};
var x=o.square(16);
document.write(x+"<br>");
函數(shù)甚至不需要帶名字垒拢,當(dāng)把它們賦值給數(shù)組元素時(shí):
chap3-16.js
var a=[function (x) {return x*x},20];
document.write(a[0](a[1])+"<br>");
作為命名空間的函數(shù)
JavaScript中變量的作用域有全局變量和局部變量2種。在JavaScript中是無法聲明只在一個(gè)代碼塊內(nèi)可見的變量的火惊,基于這個(gè)原因求类,我們常常簡單地定義一個(gè)函數(shù)用做臨時(shí)的命名空間,在這個(gè)命名空間內(nèi)定義的變量都不會(huì)污染到全局命名空間矗晃。
function mymodule() {
//模塊代碼仑嗅,這個(gè)模塊所使用的所有變量都是局部變量宴倍,而不是污染全局命名空間
}
mymodule(); //不要忘了還要調(diào)用這個(gè)函數(shù)
這段代碼僅僅定義了一個(gè)單獨(dú)的全局變量:名叫“mymodule
”的函數(shù)张症。這樣還是太麻煩,可以直接定義一個(gè)匿名函數(shù)鸵贬,并在單個(gè)表達(dá)式中調(diào)用它:
(function () {
//模塊代碼
}()); //結(jié)束函數(shù)定義并立即調(diào)用它
閉包
出于種種原因俗他,我們有時(shí)候需要得到函數(shù)內(nèi)的局部變量。閉包可以捕捉到局部變量(和參數(shù))阔逼,并一直保存下來兆衅。閉包就是一個(gè)函數(shù)引用另外一個(gè)函數(shù)的變量,因?yàn)樽兞勘灰弥圆粫?huì)被回收嗜浮,因此可以用來封裝一個(gè)私有變量羡亩。這是優(yōu)點(diǎn)也是缺點(diǎn),不必要的閉包只會(huì)徒增內(nèi)存消耗危融!
chap3-17.js
var scope="global scope"; //全局變量
function checkscope() {
var scope="local scope"; //局部變量
function f() {return scope;} //在作用域中返回這個(gè)值
return f();
}
var a=checkscope();
document.write(a+"<br>")
對象
對象是一種復(fù)合值畏铆,它將很多值聚合在一起,可通過名字訪問這些值吉殃。對象也可看作是屬性的無序集合辞居,每個(gè)屬性都是一個(gè)名/值對。屬性名是字符串蛋勺,因此我們可以把對象看成是從字符串到值的映射瓦灶。
對象除了可以保持自有的屬性外,還可以從一個(gè)稱為“原型”的對象繼承屬性抱完。
除了字符串贼陶、數(shù)字、true
、false
每界、null
和undefined
之外捅僵,JavaScript中的值都是對象。
除了包含屬性之外眨层,每個(gè)對象還擁有三個(gè)相關(guān)的對象特性:
對象的原型(prototype)指向另一個(gè)對象庙楚,本對象的屬性繼承自它的原型對象。
對象的類(class)是一個(gè)標(biāo)識(shí)對象類型的字符串趴樱。
對象的擴(kuò)展標(biāo)記(extensible flag)指明了(在ECMAScript 5中)是否可以向該對象添加新屬性馒闷。
JavaScript對象的類別
- 內(nèi)置對象:是由ECMAScript規(guī)范定義的對象或類。例如叁征,數(shù)組纳账,函數(shù),日期和正則表達(dá)式捺疼。
- 宿主對象:是由JavaScript解釋器所嵌入的宿主環(huán)境(比如Web瀏覽器)定義的疏虫。客戶端JavaScript中表示網(wǎng)頁結(jié)構(gòu)的
HTMLElement
對象均是宿主對象啤呼。 - 自定義對象:是由運(yùn)行中的JavaScript代碼創(chuàng)建的對象卧秘。
創(chuàng)建對象
創(chuàng)建對象(3種方式):
-
對象直接量:是由若干屬性名/值
var empty={}; //空對象,沒有任何屬性 var point={x:0,y:0}; //兩個(gè)屬性 var book={ "main title":"JavaScript", //屬性名字里有空格官扣,必須用字符串表示 "sub-title":"The Definitive Guide", //屬性名字里有連字符翅敌,必須用字符串表示 "for":"all audiences", //"for"是保留字,因此必須用引號(hào) author:{ //這個(gè)屬性的值是一個(gè)對象 firstname:"Shulin", lastname:"Chen" } };
-
通過
new
創(chuàng)建對象:new
關(guān)鍵字創(chuàng)建并初始化一個(gè)新對象惕蹄,new
后跟隨一個(gè)函數(shù)調(diào)用蚯涮。這里的函數(shù)稱作構(gòu)造函數(shù)。例如:var author=new Object(); //創(chuàng)建一個(gè)空對象 author.firstname="Shulin"; author.lastname="Chen"; var mycars=new Array(); mycars[0]="Saab"; mycars[1]="Volvo"; var today = new Date(); //Date 對象自動(dòng)使用當(dāng)前的日期和時(shí)間作為其初始值卖陵。
-
Object.create(proto[, propertiesObject])
是ECMAScript 5中提出的一種新的對象創(chuàng)建方式遭顶,第一個(gè)參數(shù)是要繼承的原型,也可以傳一個(gè)null
泪蔫,第二個(gè)參數(shù)是對象的屬性描述符棒旗,這個(gè)參數(shù)是可選的。例如:var o1 = Object.create({x:1,y:2}); //o1繼承了屬性x和y var o2 = Object.create(Object.prototype); //o2和{}以及new Object()一樣鸥滨,創(chuàng)建了一個(gè)普通的空對象
如果
proto
參數(shù)不是null
或一個(gè)對象嗦哆,則拋出一個(gè) TypeError 異常。-
在ECMAScript 3中可以用類似下面的代碼來模擬原型繼承:
chap3-18.js
//inherit()返回了一個(gè)繼承自原型對象p的屬性的新對象 //這里使用ECMAScript 5中的Object.create()函數(shù)(如果存在的話) //如果不存在Object.create()婿滓,則退化使用其它方法 function inherit(p) { if(p==null) throw TypeError(); //p是一個(gè)對象老速,但不能是null if(Object.create) return Object.create(p); //如果Object.create()存在,直接使用它 var t=typeof p; if(t!=="object" && t!=="function") throw TypeError(); function f() {}; //定義一個(gè)空構(gòu)造函數(shù) f.prototype=p; //將其原型屬性設(shè)置為p return new f(); //使用f()創(chuàng)建p的繼承對象 } //Inherit()函數(shù)的其中一個(gè)用途就是防止函數(shù)無意間(非惡意地)修改那些不受你控制的對象凸主。 // 不是將對象直接作為參數(shù)傳入函數(shù)橘券,而是將它的繼承對象傳入函數(shù)蝗锥。 //如果給繼承對象的屬性賦值颈墅,則這些屬性只會(huì)影響這個(gè)繼承對象自身灵嫌,而不是原始對象铭污。 var o={x:"don't change this value"}; changex(inherit(o)); function changex(obj) { obj.x="hello world!"; document.write(obj.x+"<br>"); } document.write(o.x+"<br>"); changex(o); document.write(o.x+"<br>");
屬性的查詢和設(shè)置
JavaScript為屬性訪問定義了兩種語法:
對象名.屬性名
或 對象名[表達(dá)式]
其中,表達(dá)式
指定要訪問的屬性的名稱或者代表要訪問數(shù)組元素的索引箭窜。
對于點(diǎn)(.
)來說毯焕,右側(cè)必須是一個(gè)以屬性名稱命名的簡單標(biāo)識(shí)符(不能有空格、連字符等)磺樱。點(diǎn)運(yùn)算符后的標(biāo)識(shí)符不能是保留字纳猫,比如book.for
是非法的,必須使用方括號(hào)的形式訪問它們竹捉,比如book["for"]
對于方括號(hào)([]
)來說芜辕,方括號(hào)內(nèi)必須是一個(gè)計(jì)算結(jié)果為字符串的表達(dá)式。其看起來更像數(shù)組块差,只是這個(gè)數(shù)組元素是通過字符串索引而不是數(shù)字索引侵续。這種數(shù)組稱為“關(guān)聯(lián)數(shù)組”。
chap3-19.html
<script>
var book={
"main title":"JavaScript",
"sub-title":"The Definitive Guide",
"for":"all audiences",
author:{
firstname:"Shulin",
lastname:"Chen"
}
};
var a=[book,4,[5,6]];
document.write(book.author.firstname+"<br>"); //獲得book對象中author的“firstname”屬性
document.write(book["for"]+"<br>");
document.write(a[0]["main title"]+"<br>");
document.write(a[2][1]+"<br>");
book["main title"]="ECMAScript 6"; //給“main title”屬性賦值
</script>
JavaScript對象具有自有屬性(實(shí)例屬性)憨闰,也有一些屬性是從原型對象繼承而來的(繼承屬性)状蜗。
假設(shè)要查詢對象q
的屬性x
,如果q
中不存在x
起趾,則會(huì)繼續(xù)在q
的原型對象中查詢屬性x
诗舰,如果原型對象中也沒有x
警儒,但這個(gè)原型對象也有原型训裆,那么繼續(xù)在這個(gè)原型對象的原型對象上執(zhí)行查詢,直到找到x
或者查找到一個(gè)原型是null
的對象為止蜀铲”吡穑可以看到,對象的原型屬性構(gòu)成了一個(gè)“鏈”记劝,通過這個(gè)“鏈”可以實(shí)現(xiàn)屬性的繼承变姨。
chap3-20.html
<head>
<meta charset="UTF-8">
<title>chap3-20</title>
<script src="js/chap3.js"></script>
</head>
<body>
<script>
var o={}; //o從Object.prototype繼承對象的方法
o.x=1; //給o定義一個(gè)屬性x
var p=inherit(o); //p繼承o和Object.prototype
p.y=2; //給p定義一個(gè)屬性y
var q=inherit(p); //q繼承p、o和Object.prototype
q.z=3; //給q定義一個(gè)屬性z
document.write(q.x+q.y+q.z+"<br>");
</script>
</body>
假設(shè)給對象o
的屬性x
賦值厌丑,如果o
中已經(jīng)有屬性x
(這個(gè)屬性不是繼承來的)定欧,那么這個(gè)賦值操作只改變這個(gè)已有屬性x
的值。如果o
中不存在屬性x
怒竿,那么賦值操作給o
添加一個(gè)新的屬性x
砍鸠。如果之前o
繼承自屬性x
,那么這個(gè)繼承的屬性就被新創(chuàng)建的同名屬性覆蓋了耕驰。
屬性賦值操作首先檢查原型鏈爷辱,以此判定是否允許賦值操作。如果o
繼承自一個(gè)只讀屬性x
,那么賦值操作是不允許的饭弓。如果允許屬性賦值操作双饥,它也總是在原始對象上創(chuàng)建屬性或?qū)σ延械膶傩再x值,而不會(huì)去修改原型鏈弟断。
chap3-20.js
var a={
get r(){return 1;},
x:1
};
var b=inherit(a); //b繼承屬性r
b.y=1; //b定義了個(gè)屬性
b.x=2; //b覆蓋繼承來的屬性x
b.r=3; //r為只讀屬性咏花,賦值語句無效
document.write(b.r+"<br>"); //輸出1
document.write(b.x+"<br>"); //輸出2
document.write(a.x+"<br>"); //原型對象沒有修改
刪除屬性
delete
運(yùn)算符可以刪除對象的屬性。它的操作數(shù)是一個(gè)屬性訪問表達(dá)式:
delete
只是斷開屬性和宿主對象的聯(lián)系阀趴,而不會(huì)去操作對象中的屬性迟螺。
delete
運(yùn)算符只能刪除自有屬性,不能刪除繼承屬性舍咖,要?jiǎng)h除繼承屬性必須從定義這個(gè)屬性的原型對象上刪除它矩父,而且這會(huì)影響到所有繼承自這個(gè)原型的對象。
chap3-21.js
var book={
"main title":"JavaScript",
"sub-title":"The Definitive Guide",
"for":"all audiences",
author:{
firstname:"Shulin",
lastname:"Chen"
}
};
delete book.author; //book不再有屬性author
delete book["main title"]; //book不再有屬性"main title"
document.write(book.author+"<br>");
document.write(book["main title"]+"<br>");
var o=Object.create(book); //o繼承了book對象的屬性
delete o["for"]; //不能刪除繼承屬性
document.write(book["for"]+"<br>");
檢測屬性
判斷某個(gè)屬性是否存在于某個(gè)對象中可以有3種方式:
in
運(yùn)算符:如果對象的自有屬性或繼承屬性中包含這個(gè)屬性排霉,則返回true
窍株。
hasOwnProperty()
方法:對象的自有屬性返回true
,對于繼承屬性返回false
攻柠。
propertyIsEnumerable()
方法:只有檢測到是自有屬性且這個(gè)屬性的可枚舉性為true
時(shí)球订,它才返回true
。某些內(nèi)置屬性是不可枚舉的瑰钮。
var o={x:1};
var obj=Object.create(o);
obj.y=2;
"x" in obj; //輸出true
"y" in obj; //輸出true
obj.hasOwnProperty("x"); //輸出false
obj.hasOwnProperty("y"); //輸出true
obj.propertyIsEnumerable("x"); //輸出false
obj.propertyIsEnumerable("y"); //輸出true
枚舉屬性
在JavaScript中冒滩,對象的屬性分為可枚舉和不可枚舉之分,它們是由屬性的enumerable
值決定的浪谴。
JavaScript中基本包裝類型的原型屬性是不可枚舉的开睡,如Object
, Array
, Number
等。
Object
對象的propertyIsEnumerable()
方法可以判斷此對象是否包含某個(gè)屬性苟耻,并且這個(gè)屬性是否可枚舉篇恒。
for
/in
循環(huán)可以遍歷對象中所有可枚舉的對象屬性(包括對象自有屬性和繼承的屬性)。
Object.keys()
方法會(huì)返回一個(gè)由一個(gè)給定對象的自身可枚舉屬性組成的數(shù)組凶杖。
Object.getOwnPropertyNames()
方法會(huì)返回一個(gè)由一個(gè)給定對象的自身屬性組成的數(shù)組胁艰,包括可枚舉和不可枚舉的。
chap3-22.js
var po={px:1,py:2};
var o={x:3,y:4};
o.__proto__=po; //設(shè)置o的原型為po
document.write("for/in方法輸出結(jié)果:<br>");
for(property in o){
document.write(property+":"+o[property]+"<br>");
}
var propertyArray=Object.keys(o);
document.write("定義枚舉屬性前Object.keys方法輸出結(jié)果:<br>");
for(var i=0;i<propertyArray.length;i++){
document.write(propertyArray[i]+"<br>");
}
Object.defineProperties(o,{
x:{enumerable:true},
y:{enumerable:false}
});
propertyArray=Object.keys(o);
document.write("定義枚舉屬性后Object.keys方法輸出結(jié)果:<br>");
for(var i=0;i<propertyArray.length;i++){
document.write(propertyArray[i]+"<br>");
}
propertyArray=Object.getOwnPropertyNames(o);
document.write("定義枚舉屬性后Object.getOwnPropertyNames方法輸出結(jié)果:<br>");
for(var i=0;i<propertyArray.length;i++){
document.write(propertyArray[i]+"<br>");
}
屬性getter
和setter
對象屬性是由名字智蝠、值和一組特性(attribute
)構(gòu)成的腾么。在ECMAScript 5中,屬性值可以用一個(gè)或兩個(gè)方法替代杈湾,這兩個(gè)方法就是getter
和setter
解虱。由getter
和setter
定義的屬性稱作“存取器屬性”(accessorproperty),它不同于“數(shù)據(jù)屬性”(data property)毛秘。
數(shù)據(jù)屬性:包含屬性的操作特性饭寺;如:設(shè)置值阻课、是否可枚舉等。
特性名稱 | 描述 | 默認(rèn)值 |
---|---|---|
value |
設(shè)置屬性的值 | undefined |
writable |
是否可修改屬性的值艰匙;true :可修改屬性的值限煞;false :不可修改屬性的值 |
false |
enumerable |
是否可枚舉屬性;true :可枚舉员凝,可通過for /in 語句枚舉屬性署驻;false :不可枚舉 |
false |
configurable |
是否可修改屬性的特性;true :可修改屬性的特性(如把writable 從false 改為true )健霹;false :不可修改屬性的特性 |
false |
存取器屬性:包含屬性的操作特性旺上;如:設(shè)置值、是否可枚舉等糖埋。
特性名稱 | 描述 | 默認(rèn)值 |
---|---|---|
get |
屬性的返回值函數(shù) | undefined |
set |
屬性的設(shè)置值函數(shù)宣吱;含有一個(gè)賦值參數(shù) | undefined |
enumerable |
是否可枚舉屬性;true :可枚舉瞳别,可通過for /in 語句枚舉屬性征候;false :不可枚舉 |
false |
configurable |
是否可修改屬性的特性;true :可修改屬性的特性(如把writable 從false 改為true )祟敛;false :不可修改屬性的特性 |
false |
存取器也是可以繼承的疤坝。
chap3-23.html
<script>
var obj={};
//添加一個(gè)屬性,并設(shè)置為存取器屬性
Object.defineProperty(obj,"name",{
get:function () {
return this._name; //get和set里的變量不要使用屬性馆铁,如:屬性為name箕慧,get和set用的是_name
},
set:function (x) {
if(isNaN(x)) //isNaN() 函數(shù)用于檢查其參數(shù)是否是非數(shù)字值掂铐。
this._name=x;
else
this._name="name不能為純數(shù)字";
},
enumerable:true,
configurable:true
});
obj.name="12";
document.write(obj.name+"<br>");
var o=inherit(obj); //存取器也是可以繼承的
o.name="a12";
document.write(o.name+"<br>");
</script>
屬性的特性
為了實(shí)現(xiàn)屬性特性的查詢和設(shè)置操作忽舟,ECMAScript 5中定義了一個(gè)名為“屬性描述符”(property descriptor)的對象虾标,這個(gè)對象代表數(shù)據(jù)屬性特性和存取器屬性特性。
在使用Object.defineProperty
乖订、Object.defineProperties
或Object.create
函數(shù)的情況下添加數(shù)據(jù)屬性扮饶,writable
具练、enumerable
和configurable
默認(rèn)值為false
乍构。
使用對象直接量創(chuàng)建的屬性,writable
扛点、enumerable
和configurable
特性默認(rèn)為true
哥遮。
Object.getOwnPropertyDescriptor(object,propertyname)
可用來獲取描述屬性特性的描述符對象。其中object
為包含屬性的對象陵究,必需眠饮;propertyname
為屬性的名稱,必需铜邮。
chap3-24.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>chap3-24</title>
</head>
<body style="font-size: xx-large">
<script>
var o1={name:"tom"};
document.write("對象直接量仪召,屬性特性默認(rèn)為true<br>");
var desc=Object.getOwnPropertyDescriptor(o1,"name");
for(var prop in desc)
document.write(prop+":"+desc[prop]+"<br>");
var o2=Object.create(null,{
name:{value:"tom"}
});
document.write("通過Object.create創(chuàng)建寨蹋,屬性特性默認(rèn)為false<br>")
desc=Object.getOwnPropertyDescriptor(o2,"name");
for(prop in desc)
document.write(prop+":"+desc[prop]+"<br>");
</script>
</body>
</html>
三個(gè)屬性
原型屬性
是用來繼承屬性的,指向另一個(gè)對象,本對象的屬性繼承自它的原型對象扔茅。
通過對象直接量創(chuàng)建的對象使用
Object.prototype
作為它們的原型已旧;通過
new
創(chuàng)建的對象使用構(gòu)造函數(shù)的prototype
屬性來作為它們的原型;通過
Object.create()
來創(chuàng)建的對象使用第一個(gè)參數(shù)作為它們的原型召娜。
在ECMAScript5中將對象作為參數(shù)傳入Object.getPrototypeOf()
可查詢它的原型运褪;
想要檢測一個(gè)對象是否是另一個(gè)對象的原型(或處于原型鏈中),使用isPrototypeOf()
玖瘸。
var p={x:1,y:2};
var o=Object.create(p);
document.write(p.isPrototypeOf(o)+"<br>"); //返回true
document.write(Object.prototype.isPrototypeOf(o)); //返回true
類屬性
是一個(gè)字符串秸讹,用以表示對象的類型信息。只能通過toString()
這種間接的方法查詢對象的類信息雅倒。該方法返回如下格式的字符串:[object class]
很多對象繼承的toString
方法被重寫過璃诀,因此必須間接的調(diào)用Function.call()
方法:
chap3-25.html
<script>
function classOf(o) {
if(o===null) return "null";
if(o===undefined) return "undefined";
return Object.prototype.toString.call(o).slice(8,-1);//提取返回字符串的第8個(gè)到倒數(shù)第二個(gè)位置之間的字符
}
document.write("null值類屬性:"+classOf(null)+"<br>");
document.write("數(shù)組類屬性:"+classOf(new Array())+"<br>");
document.write("對象類屬性:"+classOf({})+"<br>");
document.write("字符串類屬性:"+classOf("")+"<br>");
document.write("數(shù)值類屬性:"+classOf(1)+"<br>");
document.write("布爾值類屬性:"+classOf(true)+"<br>");
document.write("日期類屬性:"+classOf(new Date())+"<br>");
document.write("正則表達(dá)式類屬性:"+classOf(new RegExp())+"<br>");
document.write("客戶端宿主對象類屬性:"+classOf(window)+"<br>");
function f() {};
document.write("函數(shù)類屬性:"+classOf(f)+"<br>");
document.write("函數(shù)對象類屬性:"+classOf(new f())+"<br>");
</script>
可擴(kuò)展屬性
用以表示是否可以給對象添加新屬性。所有內(nèi)置對象和自定義對象都是顯式可擴(kuò)展的蔑匣。
Object.isExtensible()
判斷對象是否是可擴(kuò)展的文虏。
Object.preventExtensions()
可將對象轉(zhuǎn)換為不可擴(kuò)展的,一旦對象轉(zhuǎn)換成不可擴(kuò)展的了就不能轉(zhuǎn)回可擴(kuò)展的了殖演。
類和模塊
在JavaScript中也可以定義對象的類氧秘,讓每個(gè)對象都共享某些屬性,這種"共享"的特性是非常有用的趴久。類的成員或?qū)嵗及恍傩酝柘啵靡源娣潘鼈兊臓顟B(tài),其中有些屬性定義了它們的行為(通常稱為方法)彼棍。這些行為通常是由類定義的灭忠,而且為所有實(shí)例所共享。
在JavaScript中座硕,類的實(shí)現(xiàn)是基于其原型繼承機(jī)制的弛作。如果兩個(gè)實(shí)例都從一個(gè)原型對象上繼承了屬性,我們說它們是同一個(gè)類的實(shí)例华匾。
JavaScript中類的一個(gè)重要特征是"動(dòng)態(tài)可繼承"(dynamically extendable),定義類是模塊開發(fā)和重用代碼的有效方式之一映琳。
類和原型
在JavaScript中,類的所有實(shí)例對象都從一個(gè)類型對象上繼承屬性蜘拉。因此萨西,原型對象是類的核心。
在chap3.18中定義了inherit()
函數(shù)旭旭,這個(gè)函數(shù)返回一個(gè)新創(chuàng)建的對象谎脯,然后繼承自某個(gè)原型對象。如果定義了一個(gè)原型對象持寄,然后通過inherit()
函數(shù)創(chuàng)建了一個(gè)繼承自它的對象源梭,這樣就定義了一個(gè)JavaScript類娱俺。通常,類的實(shí)例還需要進(jìn)一步的初始化废麻,通常是通過定義一個(gè)函數(shù)來創(chuàng)建并初始化這個(gè)新對象矢否。
chap3-26.html
<head><script src="js/chap3.js"></script></head>
<script>
// range: 實(shí)現(xiàn)一個(gè)能表示值的范圍的類
function range(from,to){
//使用inherit()函數(shù)來創(chuàng)建對象,這個(gè)對象繼承自下面定義的原型對象
//原型對象作為函數(shù)的一個(gè)屬性存儲(chǔ)脑溢,并定義所有“范圍對象”所共享的方法(行為)
var r = inherit(range.methods);
//儲(chǔ)存新的“范圍對象”啟始位置和結(jié)束位置(狀態(tài))
//這兩個(gè)屬性是不可繼承的僵朗,每個(gè)對象都擁有唯一的屬性
r.from = from;
r.to = to;
//返回這個(gè)新創(chuàng)建的對象
return r;
}
//原型對象定義方法,這些方法為每個(gè)范圍對象所繼承
range.methods = {
//如果x在范圍內(nèi)屑彻,則返回true验庙;否則返回false
//如果這個(gè)方法可以比較數(shù)字范圍。也可以比較字符串和日期范圍
includes:function(x){
return this.from <= x && x <= this.to;},
//對于范圍內(nèi)每個(gè)整數(shù)都調(diào)用一次f
//這個(gè)方法只可用作數(shù)字范圍
foreach:function (f){
for (var x = Math.ceil(this.from); x <= this.to ; x++) f(x);
},
//返回表示這個(gè)范圍的字符串
toString:function (){return "("+ this.from + "..." + this.to + ")";}
};
//這是使用范圍對象的一些例子
var r =range(1,3); //創(chuàng)建一個(gè)范圍對象
console.log(r.includes(2)); //true:2 在這個(gè)范圍內(nèi)
r.foreach(console.log);
console.log(r.toString());
</script>
這段代碼定義了一個(gè)工廠方法
range()
社牲,用來創(chuàng)建新的范圍對象粪薛。我們注意到,這里給range()
函數(shù)定義了一個(gè)屬性range.methods
搏恤,用以便捷地存放定義類的原型對象违寿。注意
range()
函數(shù)給每個(gè)范圍對象定義了from
和to
屬性,用以定義范圍的起始位置和結(jié)束位置熟空,這兩個(gè)屬性是非共享的藤巢,當(dāng)然也是不可繼承的。range.methods
方法都用到了from
和to
屬性息罗,而且使用了this
關(guān)鍵字掂咒,為了指代它們,二者使用this
關(guān)鍵字來指代調(diào)用這個(gè)方法的對象迈喉。任何類的方法都可以通過this
的這種基本用法來讀取對象的屬性绍刮。
類和構(gòu)造函數(shù)
構(gòu)造函數(shù)是用來初始化和創(chuàng)建對象的。使用new
調(diào)用構(gòu)造函數(shù)會(huì)創(chuàng)建一個(gè)新對象挨摸,因此孩革,構(gòu)造函數(shù)本身只需要初始化這個(gè)新對象的狀態(tài)即可。調(diào)用構(gòu)造函數(shù)的一個(gè)重要特征是得运,構(gòu)造函數(shù)的prototype
屬性被用做新對象的原型膝蜈。這意味著通過同一個(gè)構(gòu)造函數(shù)創(chuàng)建的對象都是繼承自一個(gè)相同的對象,因此它們都是一個(gè)類的成員澈圈。
chap3-27.html
<script>
//表示值的范圍的類的另一種實(shí)現(xiàn)
//這是一個(gè)構(gòu)造函數(shù)彬檀,用以初始化新創(chuàng)建的“范圍對象”
//注意,這里并沒有創(chuàng)建并返回一個(gè)對象瞬女,僅僅是初始化
function Range(from, to) {
//存儲(chǔ)這個(gè)“范圍對象”的起始位置和結(jié)束位置(狀態(tài))
//這兩個(gè)屬性是不可繼承的,每個(gè)對象都擁有唯一的屬性
this.from = from;
this.to = to;
}
//所有的“范圍對象”都繼承自這個(gè)對象
//屬性的名字必須是"prototype"
Range.prototype = {
//如果x在范圍內(nèi)努潘,則返回true;否則返回false
//這個(gè)方法可以比較數(shù)字范圍诽偷,也可以比較字符串和日期范圍
includes: function(x) {
return this.from <= x && x <= this.to;
},
//對于這個(gè)范圍內(nèi)的每個(gè)整數(shù)都調(diào)用一次f
//這個(gè)方法只可用于數(shù)字范圍
foreach: function(f) {
for (var x = Math.ceil(this.from); x <= this.to; x++) f(x);
},
//返回表示這個(gè)范圍的字符串
toString: function() {
return "(" + this.from + "..." + this.to + ")";
}
};
//這里是使用“范圍對象”的一些例子
var r = new Range(1, 3); //創(chuàng)建一個(gè)范圍對象
console.log(r.includes(2));
r.foreach(console.log);
console.log(r.toString());
</script>
一個(gè)常見的編程約定:從某種意義上來講坤学,定義構(gòu)造函數(shù)即是定義類,并且類首字母要大寫报慕,而普通的函數(shù)和方法首字母都是小寫杏愤。
Range()
函數(shù)就是通過new
關(guān)鍵字來調(diào)用的,構(gòu)造函數(shù)會(huì)自動(dòng)創(chuàng)建對象,然后將構(gòu)造函數(shù)作為這個(gè)對象的方法來調(diào)用一次曲聂,最后返回這個(gè)新對象。
上面兩個(gè)例子有一個(gè)非常重要的區(qū)別:就是原型對象的命名萍膛。在第一段示例代碼中的原型是range.methods
血崭。這種命名方式很方便同時(shí)具有很好的語義,但有過于隨意雇盖。在第二段代碼中的原型是Range.prototype
忿等,這是一個(gè)強(qiáng)制命名。對Range()
構(gòu)造函數(shù)的調(diào)用會(huì)自動(dòng)使用Range.prototype
作為新Range
對象的原型崔挖。
構(gòu)造函數(shù)和類的標(biāo)識(shí)
原型對象是類的唯一標(biāo)識(shí):當(dāng)且僅當(dāng)兩個(gè)對象繼承自同一個(gè)原型對象時(shí)贸街,它們才是屬于同一個(gè)類的實(shí)例。而初始化對象的狀態(tài)的構(gòu)造函數(shù)則不能作為類的標(biāo)識(shí)狸相,兩個(gè)構(gòu)造函數(shù)的prototype屬性可能指向同一個(gè)原型對象薛匪。那么這兩個(gè)構(gòu)造函數(shù)創(chuàng)建的實(shí)例是屬于一個(gè)類的。
盡管構(gòu)造函數(shù)不像原型那樣基礎(chǔ)脓鹃,但構(gòu)造函數(shù)是類的"外在表現(xiàn)"蛋辈。很明顯,構(gòu)造函數(shù)的名字通常用做類名将谊。比如,我們說Range()
構(gòu)造函數(shù)創(chuàng)建Range
對象冷溶,然而,更根本地講尊浓,當(dāng)使用instanceof
運(yùn)算符來檢測對象是否屬于某個(gè)類時(shí)會(huì)用到構(gòu)造函數(shù)逞频。假設(shè)這里有一個(gè)對象r
,我們想知道r
是否是Range
對象栋齿,我們來這樣寫:
r instanceof Range // 如果r繼承自Rang.prototype,則返回true
任何JavaScript函數(shù)都可以用做構(gòu)造函數(shù)苗胀,并且調(diào)用構(gòu)造函數(shù)是需要用到一個(gè)prototype
屬性,因此瓦堵,每個(gè)JavaScript函數(shù)都自動(dòng)擁有一個(gè)prototype
屬性基协。這個(gè)屬性的值是一個(gè)對象,這個(gè)對象包含唯一一個(gè)不可枚舉的屬性constructor
菇用。constructor
屬性的值是一個(gè)函數(shù)對象:
var F = function() {}; //這是一個(gè)函數(shù)對象:
var p = F.prototype; //這是F相關(guān)聯(lián)的原型對象
var c = p.constructor; //這是與原型相關(guān)的函數(shù)
c === F; //=>true 對于任意函數(shù)F.prototype.constructor == F
下圖展示了構(gòu)造函數(shù)和原型之間的關(guān)系澜驮,包括原型到構(gòu)造函數(shù)的反向引用及構(gòu)造函數(shù)創(chuàng)建的實(shí)例。
注意:在上面的例子中惋鸥,Range
重新定義了prototype
杂穷,所以創(chuàng)建對象的constructor
屬性將不再是Range()
悍缠,而是直接使用Object.prototype.constructor
,即Object()
耐量。我們可以通過補(bǔ)救措施來修正這個(gè)問題飞蚓,顯式的給原型添加一個(gè)構(gòu)造函數(shù):
Chap3-28.html
Range.prototype = {
constructor:Range, //顯式的設(shè)置構(gòu)造函數(shù)反向引用
includes: function(x) {
return this.from <= x && x <= this.to;
},
//對于這個(gè)范圍內(nèi)的每個(gè)整數(shù)都調(diào)用一次f
//這個(gè)方法只可用于數(shù)字范圍
foreach: function(f) {
for (var x = Math.ceil(this.from); x <= this.to; x++) f(x);
},
//返回表示這個(gè)范圍的字符串
toString: function() {
return "(" + this.from + "..." + this.to + ")";
}
};
另外一種常見的解決辦法是使用預(yù)定義的原型對象,預(yù)定義的原型對象包含constructor
屬性廊蜒,然后依次給原型對象添加方法:
Chap3-29.html
//擴(kuò)展預(yù)定義的Range.prototype對象趴拧,而不重寫之
//這樣就自動(dòng)創(chuàng)建Range.prototype.constructor屬性
Range.prototype.includes=function(x){
return this.from <= x && x <= this.to;
};
//對于這個(gè)范圍內(nèi)的每個(gè)整數(shù)都調(diào)用一次f
//這個(gè)方法只可用于數(shù)字范圍
Range.prototype.foreach = function(f) {
for (var x = Math.ceil(this.from); x <= this.to; x++) f(x);
};
//返回表示這個(gè)范圍的字符串
Range.prototype.toString=function() {
return "(" + this.from + "..." + this.to + ")";
};
在JavaScript中定義類的步奏可以縮減為一個(gè)分三步的算法。
- 先定義一個(gè)構(gòu)造函數(shù)山叮,并設(shè)置初始化新對象的實(shí)例屬性著榴。
- 給構(gòu)造函數(shù)的
prototype
對象定義實(shí)例的方法嗅战。 - 給構(gòu)造函數(shù)定義類字段和類屬性隘竭。
Complex.js
/*這個(gè)文件定義了Complex類塘秦,用來描述復(fù)數(shù)。這個(gè)構(gòu)造函數(shù)為它所創(chuàng)建的每個(gè)實(shí)例定義了實(shí)例字段r和i动看,分別保存復(fù)數(shù)的實(shí)部和虛部*/
function Complex(real, imaginary) {
this.r = real; // The real part of the complex number.
this.i = imaginary; // The imaginary part of the number.
}
/*類的實(shí)例方法定義為原型對象的函數(shù)值的屬性
*這個(gè)庫定義的方法可以被所有實(shí)例繼承尊剔,并為它們提供共享的行為
*需要注意的是,javascript的實(shí)例方法必須使用關(guān)鍵字this才存取實(shí)例的字段*/
Complex.prototype.add = function(that) {
return new Complex(this.r + that.r, this.i + that.i);
};
Complex.prototype.equals = function(that) {
return that != null && // must be defined and non-null
that.constructor === Complex && // and an instance of Complex
this.r === that.r && this.i === that.i; // and have the same values.
};
Complex.prototype.toString = function() {
return "{" + this.r + "," + this.i + "}";
};
//類字段(比如常量)和類方法直接定義為構(gòu)造函數(shù)的屬性
//這里定義了一些對復(fù)數(shù)運(yùn)算有幫助的類的字段菱皆,它們的命名全都是大寫须误,用以表明它們是常量
Complex.ZERO = new Complex(0,0);
Complex.I = new Complex(0,1);
Chap3-30.htnl
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>chap3-30</title>
<script src="js/Complex.js"></script>
</head>
<body style="font-size: x-large">
<script>
var c = new Complex(2, 3); //使用構(gòu)造函數(shù)創(chuàng)建新對象
var d = new Complex(c.i,c.r); //用到了c的實(shí)例屬性
document.write(c.add(d).toString()+"<br>"); // {5,5}:使用了實(shí)例的方法
var e=new Complex(0,1);
document.write(e.equals(Complex.I));
</script>
</body>
</html>
類的擴(kuò)充
JavaScript中基于原型的繼承機(jī)制是動(dòng)態(tài)的:對象從其原型繼承屬性,如果創(chuàng)建對象之后原型的屬性發(fā)生改變仇轻,也會(huì)影響到繼承這個(gè)原型的所有實(shí)例對象京痢。這意味著我們可以通過給原型對象添加新的方法來擴(kuò)充JavaScript類。
Chap3-31.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>chap3-31</title>
<script src="js/Complex.js"></script>
</head>
<body>
<script>
if(!Complex.prototype.mag){
//計(jì)算復(fù)數(shù)的模篷店,復(fù)數(shù)的模的定義為原點(diǎn)(0,0)到復(fù)平面的距離
Complex.prototype.mag = function() {
return Math.sqrt(this.r*this.r + this.i*this.i);
};
}
var c = new Complex(2,3);
document.write(c.mag());
</script>
</body>
</html>
正則表達(dá)式的模式匹配
JavaScript中的正則表達(dá)式用RegExp
對象表示祭椰,可以使用RegExp()
構(gòu)造函數(shù)來創(chuàng)建RegExp
對象,不過RegExp
對象更多是通過一種特殊的直接語法量來創(chuàng)建疲陕;就像通過引號(hào)包裹字符的方式來定義字符串常量一樣方淤,這種表達(dá)式直接量定義為包含在一堆斜杠(/
)之間的字符。例如:
var pattern=/s$/; //用來匹配所有以字母“s”結(jié)尾的字符串
也可以用構(gòu)造函數(shù)RegExp()
來定義蹄殃,例如:
var pattern1=new RegExp("s$");
正則表達(dá)式的模式規(guī)則是一個(gè)字符序列組成的携茂。包括所有字母和數(shù)字在內(nèi),大多數(shù)的字符都是按照直接量僅描述待匹配的字符的窃爷。例如/java/
可以匹配任何包含"java"子串的字符串邑蒋。
直接量字符
正則表達(dá)式中所有字符和數(shù)字都是按照字面含義進(jìn)行匹配的。javascript正則表達(dá)式語法也支持非字母的字符匹配按厘,這些字符需要通過反斜線(\
)作為前綴進(jìn)行轉(zhuǎn)義医吊。
javascript正則表達(dá)式中的直接量字符:
字符 | 匹配 |
---|---|
字母和數(shù)字字符 | 自身 |
\o |
NUL字符(\u0000 ) |
\t |
制表符(\u0009 ) |
\n |
換行符(\u000A ) |
\v |
垂直制表符(\u000B ) |
\f |
換頁符(\u000C ) |
\r |
回車符(\u000D ) |
\xnn |
由十六進(jìn)制數(shù)指定的拉丁字符,例如\x0A 等價(jià)于\n
|
\uxxxx |
由十六進(jìn)制數(shù)xxxx 指定的Unicode字符逮京,例如\u0009 等價(jià)于\t
|
字符類
將直接量字符單獨(dú)放進(jìn)方括號(hào)內(nèi)就組成了字符類(character class)卿堂。一個(gè)字符類可以匹配它包含的任意字符。例如,/[abc]/
就和字母“a”草描、“b”览绿、“c”中的任意一個(gè)都匹配。
字符 | 匹配 |
---|---|
[...] |
方括號(hào)內(nèi)的任意字符 |
[^...] |
不在方括號(hào)內(nèi)的任意字符 |
. |
除換行符和其它Unicode行終止符之外的任意字符 |
\w |
任何ASCII字符組成的單詞穗慕,等價(jià)于[a-zA-Z0-9]
|
\W |
任何不是ASCII字符組成的單詞饿敲,等價(jià)于[^a-zA-Z0-9]
|
\s |
任何Unicode空白符 |
\S |
任何非Unicode空白符的字符 |
\d |
任何ASCII數(shù)字,等價(jià)于[0-9]
|
\D |
除了ASCII數(shù)字之外的任何字符逛绵,等價(jià)于[^0-9]
|
注意:在方括號(hào)之內(nèi)也可以寫成這些特殊轉(zhuǎn)義字符怀各。比如,由于\s
匹配所有的空白字符术浪,\d
匹配的是所有數(shù)字瓢对,因此,/[\s\d]/
就是匹配任意空白或數(shù)字胰苏。
Chap3-32.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>chap3-32</title>
<style type="text/css">
label{font-size: xx-large}
p>:invalid{outline: medium solid red}
p>:valid{outline: medium dotted green}
</style>
</head>
<body>
<p>
<label for="a">ASCII字符:</label>
<input type="text" id="a" pattern="\w">
</p>
<p>
<label for="b">ASCII數(shù)字:</label>
<input type="text" id="b" pattern="\d">
</p>
</body>
</html>
重復(fù)
字符 | 含義 |
---|---|
{n,m} |
匹配前一項(xiàng)至少n次硕蛹,但不能超過m次 |
{n,} |
匹配前一項(xiàng)n次或者更多次 |
{n} |
匹配前一項(xiàng)n次 |
? |
匹配前一項(xiàng)0次或1次,也就是說前一項(xiàng)是可選的硕并,等價(jià)于{0,1}
|
+ |
匹配前一項(xiàng)1次或多次法焰,等價(jià)于{1,}
|
* |
匹配前一項(xiàng)0次或多次,等價(jià)于{0,}
|
/\d{2,4}/ //匹配2~4個(gè)數(shù)字
/\w{3}\d?/ //精確匹配三個(gè)單詞和一個(gè)可選的數(shù)字
/\s+java\s+/ //匹配前后帶一個(gè)或多個(gè)空格的字符串“java”
/[^(]*/ //匹配1個(gè)或多個(gè)非左括號(hào)的字符
在使用*
和?
時(shí)要注意鲤孵,由于這些字符可能匹配0個(gè)字符壶栋,因此它們允許什么都不匹配。例如正則表達(dá)式/a*/
實(shí)際上與字符串“bbbb”匹配普监,因?yàn)檫@個(gè)字符串含有0個(gè)a贵试。
Chap3-33.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>chap3-33</title>
<style type="text/css">
label{font-size: xx-large}
p>:invalid{outline: medium solid red}
p>:valid{outline: medium dotted green}
</style>
</head>
<body>
<p>
<label for="a">匹配6~8個(gè)ASCII字符:</label>
<input type="text" id="a" pattern="\w{6,8}">
</p>
<p>
<label for="b">匹配3個(gè)ASCII字符和1個(gè)可選的ASCII數(shù)字:</label>
<input type="text" id="b" pattern="\w{3}\d?">
</p>
</body>
</html>
非貪婪的重復(fù)
上表中匹配重復(fù)字符是盡可能多地匹配嘿悬,而且允許后繼的正則表達(dá)式繼續(xù)匹配壹无。因此,我們稱之為“貪婪的”匹配速和。
我們同樣可以使用這種表達(dá)式進(jìn)行“非貪婪”的匹配廊散。只需在待匹配的字符后跟隨一個(gè)問號(hào)即可:??
桑滩、+?
、*?
或{1,5}?
允睹。比如运准,正則表達(dá)式/a+/
可以匹配一個(gè)或多個(gè)連續(xù)的字母a。當(dāng)使用“aaa”作為匹配的字符串時(shí)缭受,正則表達(dá)式會(huì)匹配它的三個(gè)字符胁澳。但是/a+?/
也可以匹配一個(gè)或多個(gè)連續(xù)字母a,但它是盡可能少的匹配米者。我們同樣將“aaa”作為匹配字符串韭畸,但最后一個(gè)模式只能匹配第一個(gè)a宇智。
使用非貪婪的匹配模式所得到的結(jié)果可能和期望的并不一致因谎。例如,/a+b/
钾腺,當(dāng)使用它來匹配“aaab”時(shí)徙垫,它會(huì)匹配了整個(gè)字符串。而/a+?b/
放棒,它匹配盡可能少的a和一個(gè)b,當(dāng)它用來匹配“aaab”時(shí)姻报,你期望它能匹配一個(gè)a和最后一個(gè)b。但實(shí)際上间螟,這個(gè)模式卻匹配了整個(gè)字符串吴旋。這是因?yàn)檎齽t表達(dá)式的匹配模式總是會(huì)尋找字符串中第一個(gè)可能匹配的位置。由于該匹配是從字符串的第一個(gè)字符開始的厢破,因此在這里不考慮它的子串中更短的匹配荣瑟。
選擇、分組和引用
正則表達(dá)式的語法還包括指定選擇項(xiàng)摩泪、子表達(dá)式分組和引用前一子表達(dá)式的特殊字符笆焰。
字符 | 含義 | |
---|---|---|
` | ` | 選擇,匹配的是該符號(hào)左邊的子表達(dá)式或右邊的子表達(dá)式 |
(...) |
組合见坑,將幾個(gè)項(xiàng)組合成一個(gè)單元嚷掠,這個(gè)單元可通過* 、+ 鳄梅、? 和` |
`等符號(hào)加以修飾叠国,而且可以記住和這個(gè)組合相匹配的字符串以供此后的引用使用 |
(?:...) |
只組合,將項(xiàng)組合到一個(gè)單元戴尸,但不記憶與該組相匹配的字符 | |
\n |
和第n個(gè)分組第一次匹配的字符相匹配粟焊,組是圓括號(hào)中子表達(dá)式(也有可能是嵌套的),組索引是從左到右的左括號(hào)數(shù)孙蒙,(?: 形式的分組不編碼 |
字符|
用于分隔供選擇的字符项棠。例如:
/ab|cd|ef/ //可以匹配字符串"ab",也可以匹配字符串"cd"挎峦,還可以匹配字符串"ef"
/\d{3}|[a-z]{4}/ //可以匹配三位數(shù)字或4個(gè)小寫字母
注意:選擇項(xiàng)的嘗試匹配總是從左到右香追,直到發(fā)現(xiàn)了匹配項(xiàng)。如果左邊的選擇項(xiàng)匹配坦胶,就忽略右邊的匹配項(xiàng)透典。即使它產(chǎn)生更好的匹配晴楔。因此,當(dāng)正則表達(dá)式/a|ab/
匹配字符串“ab”時(shí)峭咒,它只能匹配第一個(gè)字符税弃。
正則表達(dá)式中的圓括號(hào)有多種作用。
一個(gè)作用是把單獨(dú)的項(xiàng)組合成子表達(dá)式凑队,以便可以像處理一個(gè)獨(dú)立的單元那樣用|
则果、*
、+
或者?
等來對單元內(nèi)的項(xiàng)進(jìn)行處理漩氨。例如:
/java(script)?/ //可以匹配字符串"java"西壮,其后可以有"script"也可以沒有
/(ab|cd)+|ef/ //可以匹配字符串"ef",也可以匹配字符串"ab"或"cd"的一次或多次重復(fù)
Chap3-34.html
<body>
<p>
<label for="a">匹配"ab"叫惊,或"cd"款青,或"ef":</label>
<input type="text" id="a" pattern="ab|cd|ef">
</p>
<p>
<label for="b">匹配三位數(shù)字或4個(gè)小寫字母:</label>
<input type="text" id="b" pattern="\d{3}|[a-z]{4}">
</p>
<p>
<label for="b">匹配字符串"java",或"javascript":</label>
<input type="text" id="b" pattern="java(script)?">
</p>
<p>
<label for="a">匹配"ef"赋访,或匹配字符串"ab"或"cd"的一次或多次重復(fù):</label>
<input type="text" id="a" pattern="(ab|cd)+|ef">
</p>
</body>
另一個(gè)作用是允許在同一正則表達(dá)式的后部引用前面的子表達(dá)式可都。這是通過在字符\
后加一位數(shù)字來實(shí)現(xiàn)的。這個(gè)數(shù)字指定了帶圓括號(hào)的子表達(dá)式在正則表達(dá)式中的位置蚓耽。例如:
/([Jj]ava([Ss]cript)?)\sis\s(fun\w*)/ //嵌套的子表達(dá)式([Ss]cript)可以用\2來指代
注意:因?yàn)樽颖磉_(dá)式可以嵌套另一個(gè)子表達(dá)式,所以它的位置是參與計(jì)數(shù)的左括號(hào)的位置旋炒。
/['"][^'"]*['"]/ //匹配的就是位于單引號(hào)或雙引號(hào)之內(nèi)的0個(gè)或多個(gè)字符步悠。
/(['"])[^'"]*\1/ //與上面的正則表達(dá)式等價(jià)
在正則表達(dá)式中不用創(chuàng)建帶數(shù)字編碼的引用,也可以對子表達(dá)式進(jìn)行分組瘫镇。它是以(?:...)
來進(jìn)行分組鼎兽。例如:
//這種改進(jìn)的圓括號(hào)并不生成引用。所以在這個(gè)表達(dá)式中铣除,\2引用了與(fun\W*)匹配的文本谚咬。
/([Jj]ava(?:[Ss]cript)?)\sis\s(fun\w*)/
指定匹配位置
正則表達(dá)式中的錨字符:
字符 | 含義 |
---|---|
^ |
匹配字符串的開頭,在多行檢索中尚粘,匹配一行的開頭 |
$ |
匹配字符串的結(jié)尾择卦,在多行檢索中,匹配一行的結(jié)尾 |
\b |
匹配一個(gè)單詞的邊界郎嫁,簡而言之秉继,就是位于字符\w 和\W 之間的位置,或位于字符\w 和字符串開頭或者結(jié)尾之間的位置泽铛。(但需要注意尚辑,[\b] 匹配的是退格符) |
\B |
匹配非單詞邊界的位置 |
(?=p) |
零寬正向先行斷言,要求接下來的字符都與p 匹配盔腔,但不能包括匹配p 的那些字符 |
(?!p) |
零寬負(fù)向先行斷言杠茬,要求接下來的字符不與p 匹配 |
最常用的錨元素是^
,它用來匹配字符串的開始月褥,錨元素$
用來匹配字符串的結(jié)束。例如:
/^JavaScript$/ //要匹配單詞“JavaScript”
如果想匹配“Java”這個(gè)單詞本身瓢喉,可以使用/\sJava\s/
吓坚,可以匹配前后都有空格的單詞"Java"。但是這樣做有兩個(gè)問題灯荧,第一礁击。如果“Java”出現(xiàn)在字符串的開始或者結(jié)尾,就匹配不成功逗载,除非開始和結(jié)尾處各有一個(gè)空格哆窿。第二個(gè)問題是,當(dāng)找到了與之匹配的字符串時(shí)厉斟,它返回的匹配字符串的前端和后端都有空格挚躯。因此,我們使用單詞的邊界\b
來代替真正的空格符\s
進(jìn)行匹配(或定位)擦秽。這樣的正則表達(dá)式就寫成了/\bJava\b/
应闯。
元素\B
把匹配的錨點(diǎn)定位在不是單詞的邊界之處。因此拳氢,正則表達(dá)式/\B[Ss]cript/
與“JavaScript”和“postscript”匹配冻辩,但不與“script”和“Scripting”匹配。
任意正則表達(dá)式都可以作為錨點(diǎn)條件触幼。如果在符號(hào)(?=
和)
之間加入一個(gè)表達(dá)式硼瓣,它就是一個(gè)先行斷言,用以說明圓括號(hào)內(nèi)的表達(dá)式必須正確匹配置谦,但不是真正意義上的匹配堂鲤,可以使用/[Jj]ava([Ss]cript)?(?=\:)/
。這個(gè)正則表達(dá)式可以匹配“Jvascript: The Definitive Guide”中的“javascript”媒峡,但不能匹配“Java in NutShell”中的“Java”瘟栖,因?yàn)樗竺鏇]有冒號(hào)。
帶有(?!
的斷言是負(fù)向先行斷言谅阿,用以指定接下來的字符都不必匹配半哟。例如:/Java(?!Script)([A-Z]\w*)/
可以匹配“Java”后跟隨一個(gè)大寫字母和任意多個(gè)ASCII單詞,但“Java”后面不能跟隨“Script”奔穿。它可以匹配“JavaBeans”镜沽,但不能匹配“Javabeans”。
Chap3-35.html
<head><style type="text/css">
label{font-size: xx-large}
p>:invalid{outline: medium solid red}
p>:valid{outline: medium dotted green}
</style></head>
<body>
<p>
<label for="a">匹配位于單引號(hào)之內(nèi)的0個(gè)或多個(gè)字符:</label>
<input type="text" id="a" pattern="(['])[^']*\1">
</p>
<p>
<label for="a">要匹配單詞“JavaScript”:</label>
<input type="text" id="a" pattern="^JavaScript$">
</p>
<p>
<label for="a">要匹配前后都有空格的單詞“Java”:</label>
<input type="text" id="a" pattern="\sJava\s">
</p>
<p>
<label for="a">要匹配單詞“Java”:</label>
<input type="text" id="a" pattern="\bJava\b">
</p>
</body>
修飾符
和之前討論的正則表達(dá)式語法不同贱田,修飾符是放在/
符號(hào)之外的缅茉。Javascript支持三個(gè)修飾符:
字符 | 含義 |
---|---|
i |
執(zhí)行不區(qū)分大小寫的匹配 |
g |
執(zhí)行一個(gè)全局匹配,簡言之男摧,即找到所有的匹配蔬墩,而不是在找到第一個(gè)之后就停止 |
m |
多行匹配模式译打,^ 匹配一行的開頭和字符串的開頭,$ 匹配行的結(jié)束和字符串的結(jié)束 |
/java$/im //可以匹配java拇颅,也可以匹配"Java\nis Fun".
用于模式匹配的String
方法
String支持4種使用正則表達(dá)式的方法:
-
search()
:它的參數(shù)是一個(gè)正則表達(dá)式奏司,返回第一個(gè)與之匹配的子串的位置,如果找不到匹配的子串樟插,它將返回-1
韵洋。document.write("javascript".search(/script/i)); //返回4
-
replace()
:用于執(zhí)行檢索與替換操作。其中第一個(gè)參數(shù)是正則表達(dá)式黄锤,第二個(gè)參數(shù)是要進(jìn)行替換的字符串搪缨。var text="javascript and Javascript and javascript"; document.write(text.replace(/javascript/gi,"JavaScript"));
-
match()
:它唯一的參數(shù)就是一個(gè)正則表達(dá)式,返回的是一個(gè)由匹配結(jié)果組成的數(shù)組鸵熟。如果該正則表達(dá)式設(shè)置了修飾符g
,則該方法返回的數(shù)組包含字符串中所有匹配的結(jié)果副编。text="1 plus 2 equals 3"; var arr=text.match(/\d+/g);
-
split()
:將調(diào)用它的字符串拆分為一個(gè)子串組成的數(shù)組,使用的分割符是split()
的參數(shù)流强。text="1, 2, 3, 4, 5"; var arr=text.split(/\s*,\S*/); //允許兩邊可以留任意多的空白符
RegExp
對象
正則表達(dá)式是通過RegExp
對象來表示的痹届。 RegExp()
構(gòu)造函數(shù)帶有兩個(gè)字符串參數(shù),其中第一個(gè)參數(shù)包含正則表達(dá)式的主體部分打月,需要注意的是队腐,不論是字符串直接量還是正則表達(dá)式,都是用\
字符作為轉(zhuǎn)義字符的前綴僵控。第二個(gè)參數(shù)是可選的香到,它指定正則表達(dá)式的修飾符。
//全局匹配字符串中的6個(gè)數(shù)字报破,注意這里使用了"\\",而不是“\”
var zipcode=new RegExp("\\d{6}","g");
RegExp
對象的屬性
source
屬性:是一個(gè)只讀的字符串千绪,包含正則表達(dá)式的文本充易;global
屬性:是一個(gè)只讀的布爾值,用以說明這個(gè)正則表達(dá)式是否帶有修飾符g
荸型;ignoreCase
屬性:是一個(gè)只讀的布爾值盹靴,用以說明正則表達(dá)式是否帶有修飾符i
;multiline
屬性:是一個(gè)只讀的布爾值瑞妇,用以說明正則表達(dá)式是否帶有修飾符m
稿静;lastIndex
屬性:是一個(gè)可讀/寫的整數(shù),如果匹配模式帶有g
修飾符辕狰,這個(gè)屬性存儲(chǔ)在整個(gè)字符串中下一次檢索的開始位置改备,這個(gè)屬性會(huì)被exec()
和test()
方法用到。
Chap3-36.html
<script>
document.write("javascript".search(/script/i)); //返回4
var text="javascript and Javascript and javascript";
document.write("<br>");
document.write(text.replace(/javascript/gi,"JavaScript"));
document.write("<br>");
text="1 plus 2 equals 3";
var arr=text.match(/\d+/g);
for(var i in arr)
document.write(arr[i]+"<br>");
text="1, 2, 3, 4, 5";
var arr=text.split(/\s*,\S*/); //允許兩邊可以留任意多的空白符
for(var i in arr)
document.write(arr[i]);
//全局匹配字符串中的6個(gè)數(shù)字蔓倍,注意這里使用了"\\"悬钳,而不是“\”
var zipcode=new RegExp("\\d{6}","g");
document.write("<br>");
document.write(zipcode.source+"<br>");
document.write(zipcode.global+"<br>");
</script>
RegExp
對象的方法
exec()
方法:用于檢索字符串中的正則表達(dá)式的匹配盐捷。語法:
RegExpObject.exec(string)
如果
exec()
找到了匹配的文本,則返回一個(gè)結(jié)果數(shù)組默勾。否則碉渡,返回null
。此數(shù)組的第0個(gè)元素是與正則表達(dá)式相匹配的文本母剥,第1個(gè)元素是與RegExpObject
的第1個(gè)子表達(dá)式相匹配的文本(如果有的話)滞诺,第2個(gè)元素是與RegExpObject
的第2個(gè)子表達(dá)式相匹配的文本(如果有的話),以此類推环疼。在調(diào)用非全局的
RegExp
對象的exec()
方法時(shí)习霹,返回的數(shù)組與調(diào)用方法String.match()
返回的數(shù)組是相同的。-
當(dāng)
RegExpObject
是一個(gè)全局正則表達(dá)式時(shí)秦爆,它會(huì)在RegExpObject
的lastIndex
屬性指定的字符處開始檢索字符串string
序愚。當(dāng)exec()
找到了與表達(dá)式相匹配的文本時(shí),在匹配后等限,它將把RegExpObject
的lastIndex
屬性設(shè)置為匹配文本的最后一個(gè)字符的下一個(gè)位置爸吮。這就是說,您可以通過反復(fù)調(diào)用exec()
方法來遍歷字符串中的所有匹配文本望门。當(dāng)exec()
再也找不到匹配的文本時(shí)形娇,它將返回null
。注意:如果在一個(gè)字符串中完成了一次模式匹配之后要開始檢索新的字符串筹误,就必須手動(dòng)地把
lastIndex
屬性重置為0桐早。
test()
方法:用于檢測一個(gè)字符串是否匹配某個(gè)模式。語法:
RegExpObject.test(string)
- 如果字符串
string
中含有與RegExpObject
匹配的文本厨剪,則返回true
哄酝,否則返回false
。
Chap3-37.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>chap3-37</title>
</head>
<body>
<script>
var str="Visit W3School";
var patt=new RegExp("W3School","g");
var result;
while ((result=patt.exec(str))!=null){
document.write(result+"<br>");
document.write(patt.lastIndex+"<br>");
}
var patt1=new RegExp("W3School");
var result=patt1.test(str);
document.write("Result: "+result+"<br>");
</script>
</body>
</html>
客戶端JavaScript
document對象
Window對象
使用DOM元素
腳本化CSS
腳本化HTTP
jQuery類庫
客戶端存儲(chǔ)
JSON
document對象
文檔對象模型DOM把JavaScript和HTML文檔的內(nèi)容聯(lián)系起來祷膳。通過使用DOM陶衅,可以添加、移除和操作各種元素直晨,還可以使用事件(event)來響應(yīng)用戶的交互操作搀军,以及完全控制CSS。
document對象是通往DOM功能的入口勇皇,它向你提供了當(dāng)前文檔的信息罩句,以及一組可供探索、導(dǎo)航敛摘、搜索或操作結(jié)構(gòu)與內(nèi)容的功能门烂。
問題 | 解決方案 |
---|---|
獲取文檔信息 | 使用document 元數(shù)據(jù)屬性 |
獲取文檔位置信息 | 使用document.location 屬性 |
導(dǎo)航至某個(gè)新文檔 | 修改Location對象的某個(gè)屬性值 |
讀取和寫入cookie | 使用document.cookie 屬性 |
判斷瀏覽器處理文檔的進(jìn)展情況 | 使用document.readystate 屬性 |
獲取瀏覽器已實(shí)現(xiàn)的DOM功能詳情 | 使用document.implementation 屬性 |
獲取代表特定元素類型的對象 | 使用document 屬性,如images 着撩、links
|
在文檔中搜索元素 | 使用以document.getElement 開頭的各種方法 |
用CSS選擇器在文檔中搜索元素 | 使用document.querySelector 或document.querySelectorAll 方法 |
合并進(jìn)行鏈?zhǔn)剿阉饕詫ふ以?/td> | 對之前搜索的結(jié)果調(diào)用搜索方法 |
在DOM樹中導(dǎo)航 | 使用文檔/元素的方法與屬性诅福,如hasChildNodes()
|
使用document
元數(shù)據(jù)
元數(shù)據(jù)屬性 | 說明 |
---|---|
characterSet |
返回文檔的字符集編碼匾委。只讀 |
charset |
獲取或設(shè)置文檔的字符集編碼 |
compatMode |
獲取文檔的兼容性模式 |
cookie |
獲取或設(shè)置當(dāng)前文檔的cookie |
defaultCharset |
獲取瀏覽器所使用的默認(rèn)字符編碼 |
dir |
獲取或設(shè)置文檔的文本方向 |
domain |
獲取或設(shè)置當(dāng)前文檔的域名 |
implementation |
提供可用DOM功能的信息 |
lastModified |
返回文檔的最后修改時(shí)間(如果修改時(shí)間不可用則返回當(dāng)前時(shí)間) |
location |
提供當(dāng)前文檔的URL信息 |
readyState |
返回當(dāng)前文檔的狀態(tài)。只讀 |
referrer |
返回鏈接到當(dāng)前文檔的文檔URL |
title |
獲取或設(shè)置當(dāng)前文檔的標(biāo)題 |
Chap3-38.html
<head>
<meta charset="UTF-8">
<title>chap3-38</title>
<style type="text/css">
pre{font-size: xx-large}
</style>
</head>
<body>
<script>
document.dir="rtl";
document.writeln("<pre>");
document.writeln("characterSet:"+document.characterSet);
document.writeln("charset:"+document.charset);
document.writeln("compactMode:"+document.compatMode);
document.writeln("defaultCharset:"+document.defaultCharset);
document.writeln("dir:"+document.dir);
document.writeln("domain:"+document.domain);
document.writeln("lastModified:"+document.lastModified);
document.writeln("referrer:"+document.referrer);
document.writeln("title:"+document.title);
document.writeln("</pre>");
</script>
compatMode屬性返回值有兩個(gè):
CSS1Compat
:代表此文檔遵循某個(gè)有效的HTML規(guī)范(但不必是HTML5,有效的HTML4文檔也會(huì)返回這個(gè)值)BackCompat
:代表此文檔含有非標(biāo)準(zhǔn)的功能,已觸發(fā)怪異模式
使用Location對象
Location對象的屬性和方法 | 說明 |
---|---|
protocol |
獲取或設(shè)置文檔URL的協(xié)議部分 |
host |
獲取或設(shè)置文檔URL的主機(jī)和端口部分 |
href |
獲取或設(shè)置當(dāng)前文檔的地址 |
hostname |
獲取或設(shè)置文檔URL的主機(jī)名部分 |
port |
獲取或設(shè)置文檔URL的端口部分 |
pathname |
獲取或設(shè)置文檔URL的路徑部分 |
search |
獲取或設(shè)置文檔URL的查詢(問號(hào)串)部分 |
hash |
獲取或設(shè)置文檔URL的錨(井號(hào)串)部分 |
assign(URL) |
導(dǎo)航到指定的URL上 |
replace(URL) |
清除當(dāng)前文檔并導(dǎo)航到URL所指定的那個(gè)文檔 |
reload() |
重新載入當(dāng)前的文檔 |
resolveURL(URL) |
將指定的相對URL解析成絕對URL |
Chap3-39.html
<body>
<button id="pressme">Press Me</button>
<script>
document.writeln("<pre>");
document.writeln("protocol:"+document.location.protocol);
document.writeln("host:"+document.location.host);
document.writeln("hostname:"+document.location.hostname);
document.writeln("href:"+document.location.href);
document.writeln("port:"+document.location.port);
document.writeln("pathname:"+document.location.pathname);
document.writeln("search:"+document.location.search);
document.writeln("hash:"+document.location.hash);
document.writeln("</pre>");
document.getElementById("pressme").onclick=function () {
document.location.assign("chap3-38.html");
}
</script>
</body>
讀取和寫入cookie
cookie屬性讓你可以讀取痴柔、添加和更新文檔所關(guān)聯(lián)的cookie颜骤。cookie是形式為name=value
的名稱/值對。如果存在多個(gè)cookie,那么cookie屬性會(huì)把它們一起返回,之間以分號(hào)間隔。
在創(chuàng)建cookie時(shí)浅役,可以添加額外字段來改變cookie的處理方式:
額外項(xiàng) | 說明 |
---|---|
path=path |
設(shè)置cookie關(guān)聯(lián)的路徑,如果沒有指定則默認(rèn)使用當(dāng)前文檔的路徑 |
domain=domain |
設(shè)置cookie關(guān)聯(lián)的域名伶唯,如果沒有指定則默認(rèn)使用當(dāng)前文檔的域名 |
max-age=seconds |
設(shè)置cookie的有效期觉既,以秒的形式從它創(chuàng)建之時(shí)起開始計(jì)算 |
expires=date |
設(shè)置cookie的有效期,用的是GMT格式的日期乳幸,如果沒有指定則cookie會(huì)在對話結(jié)束時(shí)過期 |
secure |
只有在安全(HTTPS)連接時(shí)才會(huì)發(fā)送cookie |
Chap3-40.html
<body><p id="cookiedata"></p><button id="write">Add Cookie</button>
<button id="update">Update Cookie</button><button id="read">Read Cookie</button>
<button id="maxage">max-age</button>
<script>
var cookieCount=0;
document.getElementById("update").onclick=function () {
document.cookie="Cookie_"+cookieCount+"=Updated_"+cookieCount;
readCookies();
}
document.getElementById("write").onclick=function () {
cookieCount++;
document.cookie="Cookie_"+cookieCount+"=Value_"+cookieCount;
readCookies();
}
document.getElementById("read").onclick=function () {
readCookies();
}
document.getElementById("maxage").onclick=function () {
document.cookie="Cookie_"+cookieCount+"=Updated_"+cookieCount+";max-age=5";
}
function readCookies() {
document.getElementById("cookiedata").innerHTML=document.cookie;
}
</script></body>
readyState
屬性
document.readyState
屬性提供了加載和解析HTML文檔過程中當(dāng)前處于哪個(gè)階段的信息瞪讼。在默認(rèn)情況下,瀏覽器會(huì)在遇到文檔里的script
元素時(shí)立即開始執(zhí)行腳本粹断,但你可以使用defer
屬性推遲腳本的執(zhí)行符欠。
readyState 值 |
說明 |
---|---|
loading |
瀏覽器正在加載和處理此文檔 |
interactive |
文檔已被解析,但瀏覽器還在加載其中鏈接的資源(圖像和媒體文件等) |
complete |
文檔已被解析瓶埋,所有的資源也已加載完畢 |
Chap3-41.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>chap3-41</title>
</head>
<body>
<script>
document.onreadystatechange=function () {
if(document.readyState=="interactive"){
document.getElementById("pressme").onclick=function () {
document.getElementById("results").innerHTML="Button Pressed";
}
}
}
</script>
<button id="pressme">Press Me</button>
<p id="results"></p>
</body>
</html>
使用屬性獲取HTML元素對象
屬性 | 說明 |
---|---|
activeElement | 返回一個(gè)代表當(dāng)前帶有鍵盤焦點(diǎn)元素的對象 |
body | 返回一個(gè)代表body 元素的對象 |
Embeds plugins | 返回所有代表embed 元素的對象 |
forms | 返回所有代表form 元素的對象 |
head | 返回一個(gè)代表head 元素的對象 |
images | 返回所有代表img 元素的對象 |
links | 返回所有代表文檔里具備href 屬性的a 和area 元素的對象 |
scripts | 返回所有代表script 元素的對象 |
Chap3-42.html
namedItem
方法會(huì)返回集合里帶有指定id
或name
屬性值的項(xiàng)目希柿。
<head>
<style>
div{border:medium black double;}
p{font-size: x-large;}
</style>
</head>
<body>
<div id="results"></div>
<img id="apple" src="pic/apple.jpg" height="100">
<p>I like apples</p>
<img id="sun" src="pic/sun.jpg" height="100">
<p>I love sun</p>
<script>
var resultsElement=document.getElementById("results");
var elems=document.images;
for(var i=0;i<elems.length;i++){
resultsElement.innerHTML+="Image Elements: "+elems[i].id+"<br>";
}
var srcValue=elems.namedItem("apple").src;
resultsElement.innerHTML+="Src for apple element is: "+srcValue+"<br>";
</script>
</body>
搜索元素
屬性 | 說明 |
---|---|
getElementById(id) |
返回帶有指定id 值的元素 |
getElementsByClassName(class) |
返回帶有指定class 值的元素 |
getElementsByName(name) |
返回帶有指定name 值的元素 |
getElementsByTagName(tag) |
返回指定類型的元素 |
querySelector(selector) |
返回匹配指定CSS選擇器的第一個(gè)元素 |
querySelectorAll(selector) |
返回匹配指定CSS選擇器的所有元素 |
Chap3-43.html
這個(gè)例子中的選擇器會(huì)匹配所有的p
元素和id
值為apple
的img
元素。
<head><style>p{font-size: x-large;color: white;background-color: grey}
div{font-size: x-large;border: medium double black} </style></head>
<body>
<div id="results"></div>
<img id="apple" class="pictures" name="myapple" src="pic/apple.jpg" height="100">
<p>I like apples</p>
<img id="sun" class="pictures" src="pic/sun.jpg" height="100">
<p>I love sun</p>
<script>
var resultsElement=document.getElementById("results");
var pElems=document.getElementsByTagName("p");
resultsElement.innerHTML+="There are "+pElems.length+" p elements. <br>";
var imgElems=document.getElementsByClassName("pictures");
resultsElement.innerHTML+="There are "+imgElems.length+" elements in the pictures class. <br>";
var nameElems=document.getElementsByName("myapple");
resultsElement.innerHTML+="There are "+nameElems.length+" elements with the name 'apple'. <br>";
var cssElems=document.querySelectorAll("p,img#apple");
resultsElement.innerHTML+="The selector matched "+cssElems.length+" elements. <br>";
</script>
</body>
合并進(jìn)行鏈?zhǔn)剿阉?/h4>
DOM的一個(gè)實(shí)用功能是幾乎所有Document對象實(shí)現(xiàn)的搜索方法同時(shí)也能被HTMLElement
對象實(shí)現(xiàn)养筒,從而可以合并進(jìn)行鏈?zhǔn)剿阉髟贰Nㄒ坏睦馐?code>getElementById方法,只有Document對象才能使用它晕粪。
Chap3-44.html
<head><style>p{font-size: x-large;color: white;background-color: grey}
div{font-size: x-large;border: medium double black}
span{font-size: x-large;display: block;height: 100px}
.s1{display: inline-block} </style></head>
<body>
<div id="results"></div>
<p id="tblock">
<span><img id="apple" src="pic/apple.jpg" height="100"></span>
<span>I like <span class="s1" style="color: red">apples</span> and <span class="s1" style="color: yellow">bananas</span> </span>
<span><img id="sun" src="pic/sun.jpg" height="100"></span>
<span>I love sun</span>
</p>
<script>
var resultsElement=document.getElementById("results");
var spanelems=document.getElementById("tblock").getElementsByTagName("span");
resultsElement.innerHTML+="There are "+spanelems.length+" span elements. <br>";
var imgElems=document.getElementById("tblock").querySelectorAll("img");
resultsElement.innerHTML+="There are "+imgElems.length+" img elements. <br>";
var s1elems=document.getElementById("tblock").querySelectorAll("#tblock>span");
resultsElement.innerHTML+="There are "+s1elems.length+" span (not s1) elements. <br>";
</script>
</body>
在DOM樹里導(dǎo)航
另一種搜索元素的方法是將DOM視為一棵樹盾戴,然后在它的層級(jí)結(jié)構(gòu)里導(dǎo)航。
navigation 屬性 |
說明 |
---|---|
childNodes |
返回子元素組 |
firstChild |
返回第一個(gè)子元素 |
hasChildNodes() |
如果當(dāng)前元素有子元素就返回true
|
lastChild |
返回倒數(shù)第一個(gè)子元素 |
nextSibling |
返回定義在當(dāng)前元素之后的兄弟元素 |
parentNode |
返回父元素 |
previousSibling |
返回定義在當(dāng)前元素之前的兄弟元素 |
Chap3-45.html
<head>
<meta charset="UTF-8">
<title>chap3-45</title>
<style>
p{font-size: x-large;}
div{font-size: x-large;border: medium double black}
</style>
</head>
<body id="mybody">
<div id="results"></div>
<p id="pApple"><img id="apple" src="pic/apple.jpg" height="100"></p>
<p id="pFruits">I like apples and bananas</p>
<p id="pSun"><img id="sun" src="pic/sun.jpg" height="100"></p>
<p id="pSun">I love sun</p>
<p id="pButton">
<button id="parent">Parent</button>
<button id="child">First Child</button>
<button id="prev">Prev Sibling</button>
<button id="next">Next Sibling</button>
</p>
<script>
var resultsElement=document.getElementById("results");
var element=document.body;
var buttons=document.getElementsByTagName("button");
for(var i=0;i<buttons.length;i++){
buttons[i].onclick=handleButtonClick;
}
processNewElement(element);
function handleButtonClick(e) {
if(element.style){
element.style.backgroundColor="white";
}
if(e.target.id=="parent" && element!=document.body){
element=element.parentNode;
}else if(e.target.id=="child" && element.hasChildNodes()){
element=element.firstChild;
}else if(e.target.id=="prev" && element.previousSibling){
element=element.previousSibling;
}else if(e.target.id=="next" && element.nextSibling){
element=element.nextSibling;
}
processNewElement(element);
if(element.style){
element.style.backgroundColor="lightgrey";
}
}
function processNewElement(elem) {
resultsElement.innerHTML="Element type: "+elem+"<br>";
resultsElement.innerHTML+="Element id: "+elem.id+"<br>";
resultsElement.innerHTML+="Has child nodes: "+elem.hasChildNodes()+"<br>";
if(elem.previousSibling){
resultsElement.innerHTML+="Prev sibling is: "+elem.previousSibling+"<br>";
}else {
resultsElement.innerHTML+="No prev sibling<br>";
}
if(elem.nextSibling){
resultsElement.innerHTML+="Next sibling is: "+elem.nextSibling+"<br>";
}else {
resultsElement.innerHTML+="No next sibling<br>";
}
}
</script>
</body>
Window對象
問題 | 解決方案 |
---|---|
獲取一個(gè)Window對象 | 使用document.defaultView 或全局變量window
|
獲取某個(gè)窗口的信息 | 使用window 的信息性屬性 |
與窗口進(jìn)行交互 | 使用Window對象定義的方法 |
用模式對話框窗口提示用戶 | 在某個(gè)Window對象上使用alert 兵多、confim 、prompt 和showModalDialog 方法 |
對瀏覽器歷史執(zhí)行簡單的操作 | 對Window.history 屬性返回的History 對象使用back 橄仆、forward 和go 方法 |
操控瀏覽器歷史 | 對Window.history 屬性返回的History 對象使用pushState 和replaceState 方法 |
向運(yùn)行在另一個(gè)文檔中的腳本發(fā)送消息 | 使用跨文檔消息傳遞功能 |
設(shè)置一次性或重復(fù)性計(jì)時(shí)器 | 在Window對象上使用setInterval 剩膘、setTimeout 、clearInterval 和clearTimeout 方法 |
獲取Window對象
可以用兩種方式獲得Window對象:
document對象的
defaultView
屬性全局變量
window
Chap3-46.html
<head>
<meta charset="UTF-8">
<title>chap3-46</title>
<style>
td{font-size: x-large;border: solid black thin}
th{font-size: x-large;border: solid black thin}
table{border: solid black thin}
</style>
</head>
<body>
<table>
<tr><th>outerWidth:</th><td id="owidth"></td> </tr>
<tr><th>outerHeight:</th><td id="oheight"></td> </tr>
</table>
<script>
document.getElementById("owidth").innerHTML=window.outerWidth;
document.getElementById("oheight").innerHTML=document.defaultView.outerHeight;
</script>
</body>
獲取窗口信息
窗口屬性 | 說明 |
---|---|
innerHeight |
獲取窗口內(nèi)容區(qū)域的高度 |
innerWidth |
獲取窗口內(nèi)容區(qū)域的寬度 |
outerHeight |
獲取窗口的高度盆顾,包括邊框和菜單欄等 |
outerWidth |
獲取窗口的寬度怠褐,包括邊框和菜單欄等 |
pageXOffset |
獲取窗口從左上角算起水平滾動(dòng)過的像素?cái)?shù) |
pageYOffset |
獲取窗口從左上角算起垂直滾動(dòng)過的像素?cái)?shù) |
screen |
返回一個(gè)描述屏幕的Screen對象 |
screenLeft |
獲取從窗口左邊緣到屏幕左邊緣的像素?cái)?shù)(不是所有瀏覽器都同時(shí)實(shí)現(xiàn)了這兩個(gè)屬性,或是以同樣的方法計(jì)算這個(gè)值) |
screenTop |
獲取從窗口上邊緣到屏幕上邊緣的像素?cái)?shù)(不是所有瀏覽器都同時(shí)實(shí)現(xiàn)了這兩個(gè)屬性您宪,或是以同樣的方法計(jì)算這個(gè)值) |
Chap3-46.html
<body>
<table>
<tr><th>outerWidth:</th><td id="owidth"></td> </tr>
<tr><th>outerHeight:</th><td id="oheight"></td> </tr>
<tr><th>innerWidth:</th><td id="iwidth"></td> </tr>
<tr><th>innerHeight:</th><td id="iheight"></td> </tr>
<tr><th>screenWidth:</th><td id="swidth"></td> </tr>
<tr><th>screenHeight:</th><td id="sheight"></td> </tr>
<tr><th>screenLeft:</th><td id="sleft"></td> </tr>
<tr><th>screenTop:</th><td id="stop"></td> </tr>
</table>
<script>
document.getElementById("owidth").innerHTML=window.outerWidth;
document.getElementById("oheight").innerHTML=document.defaultView.outerHeight;
document.getElementById("iwidth").innerHTML=window.innerWidth;
document.getElementById("iheight").innerHTML=window.innerHeight;
document.getElementById("swidth").innerHTML=window.screen.width;
document.getElementById("sheight").innerHTML=window.screen.height;
document.getElementById("sleft").innerHTML=window.screenLeft;
document.getElementById("stop").innerHTML=window.screenTop;
</script>
</body>
上表中使用了screen
屬性來獲取一個(gè)Screen對象奈懒,這個(gè)對象提供了顯示此窗口的屏幕信息奠涌,其屬性有:
screen 屬性 |
說明 |
---|---|
availHeight |
屏幕上可供顯示窗口部分的高度(排除工具欄和菜單欄之類) |
availWidth |
屏幕上可供顯示窗口部分的寬度(排除工具欄和菜單欄之類) |
colorDepth |
屏幕的顏色深度 |
height |
屏幕的高度 |
width |
屏幕的寬度 |
與窗口進(jìn)行交互
Window對象提供了一組方法,可以用它們與包含文檔的窗口進(jìn)行交互磷杏。
方法名稱 | 說明 |
---|---|
blur() |
讓窗口失去鍵盤焦點(diǎn) |
close() |
關(guān)閉窗口(不是所有瀏覽器都允許某個(gè)腳本關(guān)閉窗口) |
focus() |
讓窗口獲得鍵盤焦點(diǎn) |
print() |
提示用戶打印頁面 |
scrollBy(x,y) |
讓文檔相對于當(dāng)前位置進(jìn)行滾動(dòng) |
scrollTo(x,y) |
滾動(dòng)到指定的位置 |
stop() |
停止載入文檔 |
Chap3-47.html
<head><style>p{width: 1000px;font-size: large} img{display: block} </style></head>
<body>
<p><button id=“scroll”>Scroll</button><button id=“print”>Print</button>
<button id=“close”>Close</button>
</p>
<p> In ecology, primary compounds as … <img src=“pic/globalGPP.jpg”>
Gross primary production (GPP) is…. <img src=“pic/globalNPP.jpg”>
</p>
<script>
var buttons=document.getElementsByTagName("button");
for(var i=0;i<buttons.length;i++){
buttons[i].onclick=function (e) {
if(e.target.id=="print"){
window.print();
}else if(e.target.id=="close"){
window.close();
}else{
window.scrollTo(0,400);
}
}
}
</script>
</body>
對用戶進(jìn)行提示
Window對象包含一組方法溜畅,能以不同的方式對用戶進(jìn)行提示。
方法名稱 | 說明 |
---|---|
alert(msg) |
向用戶顯示一個(gè)對話框窗口并等候其被關(guān)閉 |
confirm(msg) |
顯示一個(gè)帶有確認(rèn)和取消提示的對話框窗口 |
prompt(msg,val) |
顯示對話框提示用戶輸入一個(gè)值 |
showModalDialog(url) |
彈出一個(gè)窗口极祸,顯示指定的URL |
showModalDialog
方法已經(jīng)被廣告商們嚴(yán)重濫用了慈格,很多瀏覽器對這個(gè)功能加以限制,僅允許用戶事先許可的網(wǎng)站使用遥金。
Chap3-48.html
<body>
<button id="alert">Alert</button>
<button id="confirm">Confirm</button>
<button id="prompt">Prompt</button>
<button id="modal">Modal Dialog</button>
<script>
var buttons=document.getElementsByTagName("button");
for(var i=0;i<buttons.length;i++){
buttons[i].onclick=function (e) {
if(e.target.id=="alert"){
window.alert("This is an alert");
}else if(e.target.id=="confirm"){
var confirmed=window.confirm("This is a confirm - do you want to proceed?");
alert("Confirmed? "+confirmed);
}else if(e.target.id=="prompt"){
var response=window.prompt("Enter a world","hello");
alert("The word was "+response);
}else if(e.target.id=="modal"){
window.showModalDialog("http://www.njfu.edu.cn");
}
}
}
</script>
</body>
使用瀏覽器歷史
Window.history
屬性返回一個(gè)History對象浴捆,可以對瀏覽器歷史進(jìn)行一些基本的操作。
名稱 | 說明 |
---|---|
back() |
在瀏覽器歷史中后退一步 |
forward() |
在瀏覽器歷史中前進(jìn)一步 |
go(index) |
轉(zhuǎn)到相對于當(dāng)前文檔的某個(gè)瀏覽歷史位置稿械。正值是前進(jìn)选泻,負(fù)值是后退 |
length |
返回瀏覽歷史中項(xiàng)目數(shù)量 |
Chap3-49.html
<body>
<button id="back">Back</button>
<button id="forward">Forward</button>
<button id="go">Go -1</button>
<script>
var buttons=document.getElementsByTagName("button");
for(var i=0;i<buttons.length;i++){
buttons[i].onclick=function (e) {
if(e.target.id=="back"){
window.history.back();
}else if(e.target.id=="forward"){
window.history.forward();
}else if(e.target.id=="go"){
window.history.go(-1);
}
}
}
document.writeln("<a href=\"chap3-47.html\">瀏覽歷史中項(xiàng)目數(shù):"+window.history.length+"</a>");
</script>
</body>
使用計(jì)時(shí)器
Window對象提供的計(jì)時(shí)方法有:
方法名稱 | 說明 |
---|---|
clearInterval(id) |
撤銷某個(gè)時(shí)間間隔計(jì)時(shí)器 |
clearTimeout(id) |
撤銷某個(gè)超時(shí)計(jì)時(shí)器 |
setInterval(function,time) |
創(chuàng)建一個(gè)計(jì)時(shí)器,每隔time 毫秒調(diào)用指定的函數(shù) |
setTimeout(function,time) |
創(chuàng)建一個(gè)計(jì)時(shí)器美莫,等待time 毫秒后調(diào)用指定的函數(shù) |
setTimeout
方法創(chuàng)建的計(jì)時(shí)器只執(zhí)行一次指定函數(shù)页眯,而setInterval
方法會(huì)重復(fù)執(zhí)行某個(gè)函數(shù)。這兩個(gè)方法返回一個(gè)唯一的標(biāo)識(shí)符茂嗓,可以用clearInterval
或clearTimeout
方法來撤銷計(jì)時(shí)器餐茵。
Chap3-50.html
<body>
<p id="msg"></p>
<button id="settime">Set Time</button>
<button id="cleartime">Clear Time</button>
<button id="setinterval">Set Interval</button>
<button id="clearinterval">Clear Interval</button>
<script>
var timeID,intervalID,count=0,buttons=document.getElementsByTagName("button");
for(var i=0;i<buttons.length;i++){
buttons[i].onclick=function (e) {
if(e.target.id=="settime"){
timeID=window.setTimeout(function () {
displayMsg("Timeout Expired");
},5000);
displayMsg("Timeout Set");
}else if(e.target.id=="cleartime"){
window.clearTimeout(timeID);
displayMsg("Timeout Cleared");
}else if(e.target.id=="setinterval"){
intervalID=window.setInterval(function () {
displayMsg("Interval expired. Counter: "+count++);
},1000);
displayMsg("Interval Set");
}else if(e.target.id=="clearinterval"){
window.clearInterval(intervalID);
displayMsg("Interval Cleared");
}
}
}
function displayMsg(msg) {
document.getElementById("msg").innerHTML=msg;
}
</script>
</body>
使用DOM元素
問題 | 解決方案 |
---|---|
獲取元素的信息 | 使用HTMLElement的元數(shù)據(jù)屬性 |
獲取或設(shè)置包含某個(gè)元素所屬全部類的單個(gè)字符串 | 使用className 屬性 |
檢查或修改元素的各個(gè)類 | 使用classList 屬性 |
獲取或設(shè)置元素的屬性 | 使用attribute 、getAttribute 述吸、setAttribute 忿族、removeAttribute 和hasAttribute 方法 |
獲取或設(shè)置元素的自定義屬性 | 使用dataset 屬性 |
操作元素的文本內(nèi)容 | 使用Text 對象 |
創(chuàng)建或刪除元素 | 使用以document.create 開頭的方法以及用于管理子元素的HTMLElement方法 |
復(fù)制元素 | 使用cloneNode 方法 |
移動(dòng)元素 | 使用appendChild 方法 |
比較兩個(gè)對象是否相同 | 使用isSameNode 方法 |
比較兩個(gè)元素是否相同 | 使用isEqualNode 方法 |
直接操作HTML片段 | 使用innerHTML 和outerHTML 屬性以及insertAdjacentHTML 方法 |
在文本塊里插入元素 | 使用splitText 和appendChild 方法 |
使用元素對象
HTMLElement對象提供了一組屬性,可以用來讀取和修改被代表元素的數(shù)據(jù)蝌矛。
元素?cái)?shù)據(jù)屬性 | 說明 | 元素?cái)?shù)據(jù)屬性 | 說明 |
---|---|---|---|
checked |
獲取或設(shè)置checked屬性是否存在 | id |
獲取或設(shè)置id 屬性的值 |
classList |
獲取或設(shè)置元素所屬的類列表 | lang |
獲取或設(shè)置lang 屬性的值 |
className |
獲取或設(shè)置元素所屬的類列表 | spellcheck |
獲取或設(shè)置spellcheck 屬性是否存在 |
dir |
獲取或設(shè)置dir 屬性的值 |
tabIndex |
獲取或設(shè)置tabIndex 屬性的值 |
disabled |
獲取或設(shè)置disabled 屬性是否存在 |
tagName |
返回標(biāo)簽名(標(biāo)識(shí)元素類型) |
hidden |
獲取或設(shè)置hidden 屬性是否存在 |
title |
獲取或設(shè)置title 屬性的值 |
Char3-57.html
<style>.p1{font-size: x-large;border: medium double black}
</style>
<body>
<p id="block1" lang="en" dir="ltr" class="p1" title="favFruits">
I like <span id="apple">apples</span> and <span id="banana">banana</span>.
</p>
<pre id="results"></pre>
<script>
var results=document.getElementById("results");
var elem=document.getElementById("block1");
results.innerHTML+="tag:"+elem.tagName+"\n";
results.innerHTML+="id:"+elem.id+"\n";
results.innerHTML+="dir:"+elem.dir+"\n";
results.innerHTML+="lang:"+elem.lang+"\n";
results.innerHTML+="hidden:"+elem.hidden+"\n";
results.innerHTML+="disabled:"+elem.disabled+"\n";
results.innerHTML+="classList:"+elem.classList+"\n";
results.innerHTML+="title:"+elem.title+"\n";
</script>
</body>
可以用兩種方法處理某個(gè)元素所屬的類:
-
className
屬性:它返回一個(gè)類的列表道批,通過改變這個(gè)字符串的值,可以添加或移除類入撒。 -
classList
屬性:它返回一個(gè)DOMTokenList對象隆豹。
DOMTokenList對象成員 | 說明 |
---|---|
add(class) |
給元素添加指定的類 |
contains(class) |
如果元素屬于指定的類就返回true
|
length |
返回元素所屬類的數(shù)量 |
remove(class) |
從元素上移除指定的類 |
toggle(class) |
如果類不存在就添加它,如果存在就移除它 |
Char3-57.html
<head>
<style>
.fontSize{font-size: x-large}
.border{border: medium double black}
.big{height: 100px;width: 600px;}
.small{height: 50px;width: 300px;}
.green{background-color: green;}
.blue{background-color: blue;}
.white{color: white}
.red{color: red}
pre{font-size: x-large;border: thin black solid}
</style>
</head>
<body>
<p id="block1" lang="en" dir="ltr" class="fontSize big green" title="favFruits">
I like <span id="apple">apples</span> and <span id="banana">banana</span>.
</p>
<pre id="results"></pre>
<button id="btn1">添加邊框</button>
<button id="btn2">大小變化</button>
<button id="btn3">背景色變化</button>
<button id="btn4">前景色變化</button>
<script>
var results=document.getElementById("results");
var elem=document.getElementById("block1");
var buttons=document.getElementsByTagName("button");
showElementProperties();
for(var i=0;i<buttons.length;i++){
buttons[i].onclick=function (e) {
if(e.target.id=="btn1"){
elem.className+=" border";
}else if(e.target.id=="btn2"){
elem.classList.toggle("small");
}else if(e.target.id=="btn3"){
elem.classList.toggle("blue");
}else if(e.target.id=="btn4"){
if(elem.classList.contains("white")){
elem.classList.remove("white");
elem.classList.add("red");
}else{
elem.classList.add("white");
elem.classList.remove("red");
}
}
showElementProperties();
}
}
function showElementProperties() {
results.innerHTML="tag:"+elem.tagName+"\n";
results.innerHTML+="id:"+elem.id+"\n";
results.innerHTML+="dir:"+elem.dir+"\n";
results.innerHTML+="lang:"+elem.lang+"\n";
results.innerHTML+="hidden:"+elem.hidden+"\n";
results.innerHTML+="disabled:"+elem.disabled+"\n";
results.innerHTML+="classList:"+elem.classList+"\n";
results.innerHTML+="title:"+elem.title+"\n";
}
</script>
</body>
使用元素屬性
HTMLElement對象成員 | 說明 |
---|---|
attributes |
返回應(yīng)用到元素上的屬性 |
dataset |
返回以data- 開頭的屬性 |
getAttribute(name) |
返回指定屬性的值 |
hasAttribute(name) |
如果元素帶有指定的屬性則返回true
|
removeAttribute(name) |
從元素上移除指定屬性 |
setAttribute(name,value) |
應(yīng)用一個(gè)指定名稱和值的屬性 |
Chap3-58.html
<head><style>.p1{font-size: x-large;border: medium double black}
pre{font-size: x-large;border: thin black solid}
</style></head>
<body>
<p id="block1" class="p1" lang="en-UK">
I like <span id="apple">apples</span> and <span id="banana">banana</span>.
</p>
<pre id="results"></pre>
<script>
var results=document.getElementById("results");
var elem=document.getElementById("block1");
results.innerHTML="Element has data-fruit attribute: "+ elem.hasAttribute("data-fruit")+"\n"
results.innerHTML+="Adding data-fruit attribute\n";
elem.setAttribute("data-fruit","apples");
results.innerHTML+="data-fruit value is: "+elem.getAttribute("data-fruit")+"\n";
var attrs=elem.attributes;
for(var i=0;i<attrs.length;i++){
results.innerHTML+="Name: "+attrs[i].name+" value: "+attrs[i].value+"\n";
}
</script>
</body>
使用Text對象
元素的文本內(nèi)容是由Text對象代表的茅逮,它在文檔模型里表現(xiàn)為元素的子對象璃赡。當(dāng)瀏覽器在文檔模型里生成p元素時(shí),元素自身會(huì)有一個(gè)HTMLElement對象献雅,內(nèi)容則會(huì)有一個(gè)Text對象碉考。
<p id="block1">
I like <b>apples</b> and banana.
</p>
Text對象成員 | 說明 |
---|---|
appendData(string) |
把指定字符串附加到文本塊末尾 |
data |
獲取或設(shè)置文本 |
deleteData(offset,count) |
從文本中移除字符串。第一個(gè)數(shù)字是偏移量挺身,第二個(gè)是要移除的字符數(shù)量 |
insertData(offset,string ) |
在指定偏移量處插入指定字符串 |
length |
返回字符的數(shù)量 |
replaceData(offset,count,string) |
用指定字符串替換一段文本 |
replaceWholeText(string) |
替換全部文本 |
splitText(number) |
將現(xiàn)有的Text元素在指定偏移量處一分為二 |
substringData(offset,count) |
返回文本的子串 |
wholeText |
獲取文本 |
Chap3-59.html
<body>
<p id="block1" style="font-size: x-large;border: medium double black">
I like <b id="b1">apples</b> and banana.
</p>
<pre id="results"></pre>
<button id="pressme">Press Me</button>
<script>
var results=document.getElementById("results");
var elem=document.getElementById("block1");
document.getElementById("pressme").onclick=function () {
var textElem=elem.firstChild;
results.innerHTML="The element has "+textElem.length+" chars\n";
results.innerHTML+="The element is "+textElem.wholeText+"\n";
textElem.replaceData(5,1,"Do you");
var elemB=document.getElementById("b1");
var textB=elemB.firstChild;
textB.data="oranges";
}
</script>
</body>
修改DOM
DOM操縱成員 | 說明 |
---|---|
appendChild(HTMLElement) |
將指定元素添加為當(dāng)前元素的子元素 |
cloneNode(boolean) |
復(fù)制一個(gè)元素 |
compareDocumentPosition(HTMLElement) |
判斷一個(gè)元素的相對位置 |
innerHTML |
獲取或設(shè)置元素的內(nèi)容 |
insertAdjacentHTML(pos,text) |
相對于元素插入HTML |
insertBefore(newElem,childElem) |
在第二個(gè)子元素之前插入第一個(gè)元素 |
isEqualNode(HTMLElement) |
判斷指定元素是否與當(dāng)前元素相同 |
isSameNode(HTMLElement) |
判斷指定元素是否就是當(dāng)前元素 |
outerHTML |
獲取或設(shè)置某個(gè)元素的HTML和內(nèi)容 |
removeChild(HTMLElement) |
從當(dāng)前元素上移除指定的子元素 |
replaceChild(HTMLElement, HTMLElement) |
替換當(dāng)前元素的某個(gè)子元素 |
createElement(tag) |
創(chuàng)建一個(gè)屬于指定標(biāo)簽類型的新HTMLElement對象 |
createTextNode(text) |
創(chuàng)建一個(gè)帶有指定內(nèi)容的新Text對象 |
Chap3-60.html
<head>
<meta charset="UTF-8">
<title>chap3-60</title>
<style>
table{border: solid thin black;margin: 10px}
td{border:solid thin black;padding: 4px 5px}
</style>
</head>
<body>
<table>
<thead><tr><th>Name</th><th>Color</th></tr></thead>
<tbody id="fruitsBody">
<tr><td class="fruitName">Banana</td><td class="fruitColor">Yellow</td></tr>
<tr><td>Apple</td><td>Red</td></tr>
</tbody>
</table>
<button id="add">Add Element</button>
<button id="remove">Remove Element</button>
<button id="clone">Clone Element</button>
<script>
var tableBody=document.getElementById("fruitsBody");
document.getElementById("add").onclick=function () {
var row=tableBody.appendChild(document.createElement("tr"));
row.setAttribute("id","newrow");
var col=row.appendChild(document.createElement("td"));
col.appendChild(document.createTextNode("Plum"));
row.appendChild(document.createElement("td"))
.appendChild(document.createTextNode("Purple"));
}
document.getElementById("remove").onclick=function () {
var row=document.getElementById("newrow");
row.parentNode.removeChild(row);
}
document.getElementById("clone").onclick=function () {
var newElem=tableBody.getElementsByTagName("tr")[0].cloneNode(true);
newElem.getElementsByClassName("fruitName")[0].firstChild.data="pear";
newElem.getElementsByClassName("fruitColor")[0].firstChild.data="Yellow";
tableBody.appendChild(newElem);
}
</script>
</body>
腳本化CSS
行間樣式
腳本化CSS就是使用javascript來操作CSS侯谁。引入CSS有3種方式:行間樣式、外部樣式和內(nèi)部樣式。
行間樣式又叫內(nèi)聯(lián)樣式墙贱,使用HTML的style屬性進(jìn)行設(shè)置:
<div id="test" style="height: 40px;width: 40px;background-color: blue;"></div>
element元素節(jié)點(diǎn)提供style
屬性热芹,用來操作CSS行間樣式,style
屬性指向cssStyleDeclaration對象惨撇。例如:
test.style.height = '30px';
如果一個(gè)CSS屬性名包含一個(gè)或多個(gè)連字符伊脓,CSSStyleDeclaration屬性名的格式應(yīng)該是移除連字符,將每個(gè)連字符后面緊接著的字母大寫:
<div id="test" style="height: 40px;width: 40px;background-color: blue;"></div>
console.log(test.style.backgroundColor)
-
cssText
屬性:通過cssText
屬性能夠訪問到style
特性中的CSS代碼串纺。在讀模式下丽旅,cssText
返回瀏覽器對style
特性中CSS代碼的內(nèi)部表示;在寫模式中纺棺,賦給cssText
的值會(huì)重寫整個(gè)style
特性的值榄笙。<div id="test" style="float: left">hello world</div> <button id="pressme">Press Me</button> <div id="results"></div> <p> <script> var divTest=document.getElementById("test"); document.getElementById("results").innerHTML=divTest.style.cssText; document.getElementById("pressme").onclick=function () { divTest.style.cssText="font-size:x-large;float:right;background-color: blue;color: white"; } </script>
-
length
屬性:返回內(nèi)聯(lián)樣式中的樣式個(gè)數(shù)。var divResults=document.getElementById("results"); divResults.innerHTML=divTest.style.length;
-
item()
方法:返回給定位置的CSS屬性的名稱祷蝌。var resFontsize=divTest.style.item(0);
-
getPropertyValue()
方法:返回給定屬性的字符串值茅撞。divResults.innerHTML=resFontsize+":"+divTest.style.getPropertyValue(resFontsize);
-
getPropertyPriority()
方法:如果給定的屬性使用了!important
設(shè)置,則返回important
巨朦;否則返回空字符串米丘。<div id="results" style="height: 40px!important;width: 200px;background-color: lightgray"></div> divResults.innerHTML=divResults.style.getPropertyPriority("height");
-
setProperty()
方法:將給定屬性設(shè)置為相應(yīng)的值,并加上優(yōu)先級(jí)標(biāo)志(important
或一個(gè)空字符串)糊啡,該方法無返回值拄查。語法為:setProperty(propertyName,value,priority)
divResults.style.setProperty('height','20px','important');
-
removeProperty()
方法:從樣式中刪除給定屬性,并返回被刪除屬性的屬性值棚蓄。divResults.style.removeProperty('background-color');
Chap3-51.html
<body>
<div id="test" style="float: left">hello world</div>
<p>
<button id="cssText">cssText</button>
<button id="length">Length</button>
<button id="PropertyValue">getPropertyValue</button>
<button id="PropertyPriority">getPropertyPriority</button>
<button id="setProperty">setProperty</button>
<button id="removeProperty">removeProperty</button>
</p>
<div id="results" style="height: 40px!important;width: 200px;background-color: lightgray"></div>
<script>
var divTest=document.getElementById("test");
var divResults=document.getElementById("results");
divResults.innerHTML=divTest.style.cssText;
var buttons=document.getElementsByTagName("button");
for(var i=0;i<buttons.length;i++){
buttons[i].onclick=function (e) {
if(e.target.id=="cssText"){
divTest.style.cssText="font-size:x-large;float:right;background-color: blue;color: white";
}else if(e.target.id=="length"){
divResults.innerHTML="length:"+divTest.style.length;
}else if(e.target.id=="PropertyValue"){
var resFontsize=divTest.style.item(0);
divResults.innerHTML=resFontsize+":"+divTest.style.getPropertyValue(resFontsize);
}else if(e.target.id=="PropertyPriority"){
divResults.innerHTML=divResults.style.getPropertyPriority("height");
}
else if(e.target.id=="setProperty"){
divResults.style.setProperty('height','20px','important');
}else if(e.target.id=="removeProperty"){
divResults.style.removeProperty('background-color');
}
}
}
</script>
</body>
查詢計(jì)算樣式
元素的渲染結(jié)果是多個(gè)CSS樣式博弈后的最終結(jié)果堕扶,瀏覽器會(huì)從多個(gè)來源匯聚樣式以計(jì)算出該用哪個(gè)值來顯示某一元素。瀏覽器用于顯示某個(gè)元素的CSS屬性值集合被稱為計(jì)算樣式梭依。
元素的計(jì)算樣式(computedStyle)是一組在顯示元素時(shí)實(shí)際使用的屬性值稍算,也是用一個(gè) CSSStyleDeclaration對象來表示的,但計(jì)算樣式是只讀的役拴,主要通過getComputedStyle()
方法實(shí)現(xiàn)糊探。語法為:
document.defaultView.getComputedStyle(element[,pseudo-element])
//或
window.getComputedStyle(element[,pseudo-element])
//或
getComputedStyle(element[,pseudo-element])
getComputedStyle()
方法接收兩個(gè)參數(shù):要取得計(jì)算樣式的元素和一個(gè)偽元素字符串。如果不需要偽元素信息河闰,第二個(gè)參數(shù)可以是null
科平。getComputedStyle()
方法返回一個(gè)CSSStyleDeclaration
對象,其中包含當(dāng)前元素的所有計(jì)算的樣式姜性。
Chap3-52.html
<style>
#test:before{
content: "getComputedStyle";
width: 250px;
display: inline-block;
color: blue;
}
</style>
<div id="test" style="font-size:x-large;width: 500px;border: double medium black">hello world</div>
<script>
var divTest=document.getElementById("test");
document.writeln("缺省偽元素:");
document.writeln(document.defaultView.getComputedStyle(divTest).width);
document.writeln(window.getComputedStyle(divTest).width);
document.writeln(getComputedStyle(divTest).width);
document.writeln("偽元素:");
document.writeln(getComputedStyle(divTest,":before").width);
</script>
在使用getComputedStyle()
方法的過程中擒贸,有如下注意事項(xiàng):
-
對于
font
爽雄、background
窄绒、border
等復(fù)合樣式侥蒙,各瀏覽器處理不一樣。chrome會(huì)返回整個(gè)復(fù)合樣式印机,而IE9+矢腻、firefox和safari則輸出空字符串''
document.writeln(getComputedStyle(divTest).font);
-
不論以什么格式設(shè)置顏色,瀏覽器都以
rgb()
或rgba()
的形式輸出document.writeln(getComputedStyle(divTest,":before").color);
-
在計(jì)算樣式中射赛,類似百分比等相對單位會(huì)轉(zhuǎn)換為絕對值
#test:after{content: "!"; width: 1%; display: inline-block; color: blue;}
document.writeln(getComputedStyle(divTest,":after").width);
getComputedStyle
和element.style
的相同點(diǎn)就是二者返回的都是CSSStyleDeclaration對象多柑,取相應(yīng)屬性值得時(shí)候都是采用的 CSS 駝峰式寫法。
而不同點(diǎn)就是:
-
element.style
讀取的只是元素的“內(nèi)聯(lián)樣式”楣责,即 寫在元素的style
屬性上的樣式竣灌;而getComputedStyle
讀取的樣式是最終樣式,包括了“內(nèi)聯(lián)樣式”秆麸、“嵌入樣式”和“外部樣式”初嘹。 -
element.style
既支持讀也支持寫,我們通過element.style
即可改寫元素的樣式沮趣。而getComputedStyle
僅支持讀并不支持寫入屯烦。
我們可以通過使用getComputedStyle
讀取樣式,通過element.style
修改樣式
腳本化CSS
在實(shí)際工作中房铭,我們使用javascript操作CSS樣式時(shí)驻龟,如果要改變大量樣式,會(huì)使用腳本化CSS類的技術(shù):
-
style
:我們在改變元素的少部分樣式時(shí)缸匪,一般會(huì)直接改變其行間樣式; -
cssText
:改變元素的較多樣式時(shí)翁狐,可以使用cssText
; -
css
類:更常用的是使用css類凌蔬,將更改前和更改后的樣式提前設(shè)置為類名露懒。只要更改其類名即可(參考3.2.3,Chap3-57); -
classList
:如果要改變多個(gè)類名龟梦,使用classList
更為方便(參考3.2.3隐锭,chap3-57)
<style>
.big{height: 100px;width: 100px;background-color: blue;}
.small{height: 50px;width: 50px;background-color: green;}
</style>
<div id="test" class="big" style="border: medium double black;font-size: 1em;color: white">hello world!</div>
var divTest=document.getElementById("test");
divTest.onclick=function () {
if(divTest.className=="big"){
divTest.className="small";
}else if(divTest.className=="small"){
divTest.className="big";
}
}
腳本化樣式表
CSSStyleSheet類型表示的是樣式表。我們知道计贰,引入CSS一共有3種方式钦睡,包括行間樣式、內(nèi)部樣式和外部樣式躁倒。其中荞怒,內(nèi)部樣式和外部樣式分別通過<style>
和<link>
標(biāo)簽以樣式表的形式引入,屬于CSSStyleSheet類型秧秉。
樣式表CSSStyleSheet是通過document.styleSheets
集合來表示的褐桌,它會(huì)返回一組對象集合,這些對象代表了與文檔關(guān)聯(lián)的各個(gè)樣式表象迎。
CSSStyleSheet對象成員 | 說明 |
---|---|
cssRules |
返回樣式表的規(guī)則集合 |
deleteRule(pos) |
從樣式表中移除一條規(guī)則 |
disabled |
獲取或設(shè)置樣式表的禁用狀態(tài) |
href |
返回鏈接樣式表的href
|
insertRule(rule,pos) |
插入一條新規(guī)則到樣式表中 |
media |
返回應(yīng)用到樣式表上的媒介限制集合 |
ownerNode |
返回樣式所定義的元素 |
title |
返回title 屬性的值 |
type |
返回type 屬性的值 |
獲得樣式表的基本信息
Chap3-54.html
<head>
<meta charset="UTF-8">
<title>chap3-54</title>
<style title="S1">
p{border: double medium black;background-color: lightgray}
#block1{color: white}
table{border: thin solid black;border-collapse: collapse;margin: 5px;float: left}
td{padding: 2px}
</style>
<link rel="stylesheet" title="L1" type="text/css" href="css/styles.css">
<style title="S2" media="screen AND (min-width:500px)" type="text/css">
#block2{color: yellow;font-style: italic}
</style>
</head>
<body>
<p id="block1">There are lots of different kinds of fruit</p>
<p id="block2">One of the most interesting aspects of fruit is the variety available in each country.</p>
<div id="placeholder"></div>
<script>
var placeholder=document.getElementById("placeholder");
var sheets=document.styleSheets;
for(var i=0;i<sheets.length;i++){
var newElem=document.createElement("table");
newElem.setAttribute("border","1");
addRow(newElem,"Index",i);
addRow(newElem,"href",sheets[i].href);
addRow(newElem,"title",sheets[i].title);
addRow(newElem,"type",sheets[i].type);
addRow(newElem,"ownerNode",sheets[i].ownerNode.tagName);
placeholder.appendChild(newElem);
}
function addRow(elem,header,value) {
elem.innerHTML+="<tr><td>"+header+":</td><td>"+value+"</td></tr>";
}
</script>
</body>
styles.css
a{
background-color: grey;
color: white;
}
span{
border:thin black solid;
padding: 10px;
}
禁用樣式表
CSSStyleSheet.disabled
屬性可用來一次性啟用和禁用某個(gè)樣式表里的所有樣式荧嵌。
Chap3-55.html
<head> <style>p{border: medium double black;background-color: lightgray;height: 40px}</style>
<style media="screen AND (min-width:500px)" type="text/css">
#block1{color: yellow;border: thin solid black;background-color: lightgreen} </style>
</head>
<body>
<p id="block1">There are lots of different kinds of fruit</p>
<div><button id="pressme">Press Me</button> </div>
<script>
document.getElementById("pressme").onclick=function () {
document.styleSheets[0].disabled=!document.styleSheets[0].disabled;
}
</script>
</body>
CSSRuleList對象
CSSStyleSheet.cssRules
屬性會(huì)返回一個(gè)CSSRuleList對象呛踊,它允許你訪問樣式表里的各種樣式。樣式表里的每一種CSS樣式都有一個(gè)CSSStyleRule對象代表啦撮。
CSSRuleList對象成員 | 說明 |
---|---|
item(pos) |
返回指定索引的CSS樣式 |
length |
返回樣式表里的樣式數(shù)量 |
CSSStyleRule對象成員 | 說明 |
---|---|
cssText |
獲取或設(shè)置樣式的文本(包括選擇器) |
parentStyleSheet |
獲取此樣式所屬的樣式表 |
selectorText |
獲取或設(shè)置樣式的選擇器文本 |
style |
獲取一個(gè)代表具體樣式屬性的對象 |
Chap3-56.html
<head> <style> p{border: double medium black;background-color: lightgray}
#block1{color: white;border: thick solid black;background-color: gray}
table{border: thin solid black;border-collapse: collapse;margin: 5px;float: left}
td{padding: 2px} </style>
</head>
<body>
<p id="block1">There are lots of different kinds of fruit</p>
<p id="block2">One of the most interesting aspects of fruit is the variety available in each country.</p>
<div><button id="pressme">Press Me</button> </div>
<div id="placeholder"></div>
<script>
var placeholder=document.getElementById("placeholder");
processStyleSheet();
document.getElementById("pressme").onclick=function () {
document.styleSheets[0].cssRules.item(1).selectorText="#block2";
if(placeholder.hasChildNodes()){
var childCount=placeholder.childNodes.length;
for(var i=0;i<childCount;i++){
placeholder.removeChild(placeholder.firstChild);
}
}
processStyleSheet();
}
function processStyleSheet() {
var rulesList=document.styleSheets[0].cssRules;
for(var i=0;i<rulesList.length;i++){
var rule=rulesList.item(i);
var newElem=document.createElement("table");
newElem.setAttribute("border","1");
addRow(newElem,"parentStyleSheet",rule.parentStyleSheet.title);
addRow(newElem,"selectorText",rule.selectorText);
addRow(newElem,"cssText",rule.cssText);
placeholder.appendChild(newElem);
}
}
function addRow(elem,header,value) {
elem.innerHTML+="<tr><td>"+header+":</td><td>"+value+"</td></tr>";
}
</script>
</body>
腳本化HTTP
超文本傳輸協(xié)議(HyperText Transfer Protocol, HTTP)規(guī)定Web瀏覽器如何從Web服務(wù)器獲取文檔和向Web服務(wù)器提交表單內(nèi)容谭网,以及Web服務(wù)器如何響應(yīng)這些請求和提交。
通常赃春,HTTP并不在腳本的控制下愉择,只是當(dāng)用戶單擊鏈接、提交表單和輸入U(xiǎn)RL時(shí)才發(fā)生织中。但是锥涕,用JavaScript操作HTTP是可行的,當(dāng)用window.location屬性或調(diào)用表單對象的submit()
方法時(shí)狭吼,都會(huì)初始化HTTP請求层坠。在這兩種情況下,瀏覽器會(huì)加載新頁面搏嗡。
Ajax描述了一種主要使用腳本操縱HTTP的Web應(yīng)用架構(gòu)窿春。Ajax應(yīng)用的主要特點(diǎn)是使用腳本操縱HTTP和Web服務(wù)器進(jìn)行數(shù)據(jù)交換,不會(huì)導(dǎo)致頁面重載采盒。
Web應(yīng)用可以使用Ajax技術(shù)把用戶的交互數(shù)據(jù)記錄到服務(wù)器中旧乞;也可以開始只顯示簡單頁面,之后按需加載額外的數(shù)據(jù)和頁面組件來提升應(yīng)用的啟動(dòng)時(shí)間磅氨。
Ajax起步
Ajax的關(guān)鍵在于XMLHttpRequest對象尺栖。
第一步是創(chuàng)建一個(gè)新的XMLHttpRequest對象:
var httpRequest=new XMLHttpRequest();
第二步是給XMLHttpRequest對象的readystatechange
事件設(shè)置一個(gè)事件處理器。這個(gè)事件會(huì)在請求過程中被多次觸發(fā)烦租,向你提供事情的進(jìn)展情況延赌。可以讀取XMLHttpRequest.readyState
屬性的值來確定當(dāng)前處理的是哪一個(gè)叉橱。
值 | 數(shù)值 | 說明 |
---|---|---|
UNSENT |
0 |
已創(chuàng)建XMLHttpRequest對象 |
OPENED |
1 |
已調(diào)用open 方法 |
HEADERS_RECEIVED |
2 |
已收到服務(wù)器響應(yīng)的標(biāo)頭 |
LOADING |
3 |
已收到服務(wù)器響應(yīng) |
DONE |
4 |
響應(yīng)完成或已失敗挫以,如請求成功,HTTP狀態(tài)碼為200 |
第三步是告訴XMLHTTPRequest對象你想要做什么窃祝,比如調(diào)用open
方法請求打開文檔:
httpRequest.open(“GET”,“chap3-58.html”);
第四步是調(diào)用send
方法掐松,向服務(wù)器發(fā)送請求:
httpRequest.send();
XMLHttpRequest.responseText
屬性可以用來獲得服務(wù)器發(fā)送的數(shù)據(jù),例如:
document.getElementById("results").innerHTML=httpRequest.responseText;
responseText
屬性會(huì)返回一個(gè)字符串粪小,代表從服務(wù)器上取回的數(shù)據(jù)大磺。
Chap3-61.html
<body>
<div>
<button>chap3-58.html</button>
<button>chap3-59.html</button>
<button>chap3-60.html</button>
</div>
<div id="results" style="border: dotted medium black">Press a button</div>
<script>
var buttons=document.getElementsByTagName("button");
for(var i=0;i<buttons.length;i++){
buttons[i].onclick=function (e) {
var httpRequest=new XMLHttpRequest();
httpRequest.onreadystatechange=function (e) {
if(e.target.readyState==XMLHttpRequest.DONE && e.target.status==200){
document.getElementById("results").innerHTML=e.target.responseText;
}
};
httpRequest.open("GET",e.target.innerHTML);
httpRequest.send();
}
}
</script>
</body>
使用Ajax事件
事件名稱 | 說明 |
---|---|
abort |
在請求被中止時(shí)觸發(fā) |
error |
在請求失敗時(shí)觸發(fā) |
timeout |
如果請求超時(shí)則觸發(fā) |
readystatechange |
在請求生命周期的不同階段觸發(fā) |
loadstart |
在請求開始時(shí)觸發(fā) |
progress |
觸發(fā)以提示請求的進(jìn)度 |
load |
在請求成功完成時(shí)觸發(fā) |
loadend |
在請求已完成時(shí)觸發(fā),無論成功還是失敗 |
除了readystatechange之外探膊,其他事件都定義于XMLHttpRequest規(guī)范的第二級(jí)杠愧。調(diào)度這些事件時(shí),瀏覽器會(huì)對readystatechange事件使用常規(guī)的Event對象逞壁,對其他事件則使用ProgressEvent對象流济。
名稱 | 說明 |
---|---|
lengthComputable |
如果能夠計(jì)算數(shù)據(jù)流的總長度則返回true
|
loaded |
返回當(dāng)前已載入的數(shù)據(jù)量 |
total |
返回可用的數(shù)據(jù)總量 |
Chap3-62.html
<div><button>chap3-57.html</button><button>chap3-58.html</button><button>chap3-59.html</button></div>
<table id="events" border="1"></table><div id="target">Press a button</div>
<script>
var tableElem=document.getElementById("events"),buttons=document.getElementsByTagName("button");
for(var i=0;i<buttons.length;i++){buttons[i].onclick=handleButtonPress;}
var httpRequest;
function handleButtonPress(e) {
clearEventDetails();
httpRequest=new XMLHttpRequest();
httpRequest.onreadystatechange=handleResponse;
httpRequest.onerror=handleError;
httpRequest.onload=handleLoad;
httpRequest.onloadend=handleLoadEnd;
httpRequest.onloadstart=handleLoadStart;
httpRequest.onprogress=handleProgress;
httpRequest.open("GET",e.target.innerHTML);
httpRequest.send();
}
function handleResponse(e) {
displayEventDetails("readystate("+httpRequest.readyState+")");
if(httpRequest.readyState==4&&httpRequest.status==200){
document.getElementById("target").innerHTML=httpRequest.responseText;
}
}
function handleError(e) {displayEventDetails("error",e);}
function handleLoad(e) {displayEventDetails("load",e);}
function handleLoadEnd(e) {displayEventDetails("loadend",e);}
function handleLoadStart(e) {displayEventDetails("loadstart",e);}
function handleProgress(e) {displayEventDetails("progress",e);}
function clearEventDetails() { tableElem.innerHTML="<tr><th>Event</th><th>lengthComputable</th><th>loaded</th><th>total</th></tr>"
}
function displayEventDetails(eventName,e) {
if(e){ tableElem.innerHTML+="<tr><td>"+eventName+"</td><td>"+e.lengthComputable+"</td><td>"+e.loaded+"</td><td>"+e.total+"</td></tr>";
}else {
tableElem.innerHTML+="<tr><td>"+eventName+"</td><td>NA</td><td>NA</td><td>NA</td></tr>"
}
}
</script>
jQuery
jQuery是一個(gè)JavaScript庫锐锣,jQuery極大地簡化了 JavaScript編程,jQuery很容易學(xué)習(xí)袭灯。jQuery 庫包含以下特性:
- HTML 元素選取和操作
- CSS 操作
- HTML 事件函數(shù)
- JavaScript 特效和動(dòng)畫
- HTML DOM 遍歷和修改
- AJAX
共有兩個(gè)版本的jQuery可供下載:一份是精簡過的刺下,另一份是未壓縮的(供調(diào)試或閱讀)。這兩個(gè)版本都可從jQuery.com下載稽荧。
如需使用 jQuery,需要把它包含在希望使用的網(wǎng)頁中工腋∫陶桑可以使用 HTML 的 <script>
標(biāo)簽引用它:
<script src="jquery.js"></script>
jQuery 語法是為 HTML 元素的選取編制的,可以對元素執(zhí)行某些操作擅腰◇瘢基礎(chǔ)語法是:
$(selector).action()
- 美元符號(hào)定義 jQuery
- 選擇符(selector)"查詢"和"查找" HTML 元素
- jQuery 的 action() 執(zhí)行對元素的操作
$(this).hide() //隱藏當(dāng)前元素
$("p").hide() //隱藏所有段落
$(".test").hide() //隱藏所有 class="test" 的所有元素
$("#test").hide() //隱藏所有 id="test" 的元素
CSS選擇符
jQuery中有3種基本的選擇符:
選擇符 | CSS | jQuery | 說明 |
---|---|---|---|
標(biāo)簽名 | P |
$('p') |
取得文檔中所有的段落 |
ID | #some-id |
$('#some-id') |
取得文檔中ID為some-id 的一個(gè)元素 |
類 | .some-class |
$('.some-class') |
取得文檔中類為some-class 的所有元素 |
當(dāng)在jQuery中使用$(document).ready()
時(shí),位于其中的所有代碼都會(huì)在DOM加載后立即執(zhí)行趁冈。
Chap3-63.html
<head><script src="js/jquery-3.3.1.js"></script>
<style>.horizontal{float: left;list-style: none;margin: 10px}
.subLevel{background-color: lightgray}
ul{font-size: x-large}
</style></head>
<body><p><ul id="selected">
<li>Fruits<ul><li>apple</li><li>banana</li><li>orange</li><li>pear</li></ul></li>
<li>Vegetables<ul><li>cabbage</li><li>tomato</li><li>potato</li><li>lettuce</li></ul></li>
<li>Meat<ul><li>pork</li><li>beef</li><li>chicken</li><li>lamb</li></ul></li>
</ul></p>
<p><button id="horizontal-level">Horizontal CSS</button><button id="sub-level">Sub-level CSS</button></p>
<script>
$(document).ready(function () {
$("#horizontal-level").click(function () {
$('#selected>li').addClass('horizontal');
});
$("#sub-level").click(function () {
$("#selected li:not(.horizontal)").addClass("subLevel");
});
})
</script>
</body>
屬性選擇符
jQuery也支持屬性選擇符歼争,CSS屬性選擇符詳細(xì)內(nèi)容參照第2章CSS。
例如:要選擇帶有alt
屬性的所有圖像元素渗勘,可以使用以下代碼:$("img[alt]")
要選擇帶有href
屬性且以mailto
開頭的錨元素沐绒,可以使用:$("a[href^=mailto:]")
要選擇所有PDF文件的鏈接,可以使用:$("a[href$=.pdf]")
自定義選擇符
除了各種CSS選擇符之外旺坠,jQuery還添加了獨(dú)有的完全不同的自定義選擇符:
選擇器 | 實(shí)例 | 說明 |
---|---|---|
:first |
$("p:first") |
第一個(gè)<p> 元素 |
:last |
$("p:last") |
最后一個(gè)<p> 元素 |
:even |
$("tr:even") |
所有偶數(shù)<tr> 元素 |
:odd |
$("tr:odd") |
所有奇數(shù)<tr> 元素 |
:eq(index) |
$("ul li:eq(3)") |
列表中的第四個(gè)元素(index 從0開始) |
:gt(no) |
$("ul li:gt(3)") |
列出index 大于3的元素 |
:lt(no) |
$("ul li:lt(3)") |
列出index 小于3的元素 |
:not(selector) |
$("input:not(:empty)") |
所有不為空的input 元素 |
:header |
$(":header") |
所有標(biāo)題元素<h1> -<h6>
|
:contains(text) |
$(":contains('W3School')") |
包含指定字符串的所有元素 |
:empty |
$(":empty") |
無子(元素)節(jié)點(diǎn)的所有元素 |
:hidden |
$("p:hidden") |
所有隱藏的<p> 元素 |
:visible |
$("table:visible") |
所有可見的表格 |
Chap3-64.html
<head><script src="js/jquery-3.3.1.js"></script>
<style> tr{background-color: lightgray} .even{background-color: lightgreen}
.first{font-weight: bolder} .last{font-style: italic}
.eq0{color: red} .gt4{color: red} .contain{text-align: center}
</style></head>
<body>
<table width="300px">
<tr><td>Fruits</td><td>Color</td></tr><tr><td>apple</td><td>red</td></tr>
<tr><td>banana</td><td>yellow</td></tr><tr><td>pear</td><td>yellow</td></tr>
<tr><td>plum</td><td>purple</td></tr><tr><td colspan="2">My favorite fruits</td></tr>
</table>
<script>
$(document).ready(function () {
$("tr:even").addClass("even");
$("tr:first").addClass("first");
$("tr:last").addClass("last");
$("tr:eq(0)").addClass("eq0");
$("tr:gt(4)").addClass("gt4");
$("tr:contains('yellow')").addClass("contain");
});
</script>
</body>
在操作表單時(shí)乔遮,jQuery的自定義選擇符也可以簡化選擇元素的任務(wù):
選擇器 | 實(shí)例 | 說明 |
---|---|---|
:input |
$(":input") |
所有<input> 元素 |
:text |
$(":text") |
所有type="text" 的<input> 元素 |
:password |
$(":password") |
所有type="password" 的 <input> 元素 |
:radio |
$(":radio") |
所有type="radio" 的<input> 元素 |
:checkbox |
$(":checkbox") |
所有type="checkbox" 的<input> 元素 |
:submit |
$(":submit") |
所有type="submit" 的<input> 元素 |
:reset |
$(":reset") |
所有type="reset" 的<input> 元素 |
:button |
$(":button") |
所有type="button" 的<input> 元素 |
:image |
$(":image") |
所有type="image" 的<input> 元素 |
:file |
$(":file") |
所有type="file" 的<input> 元素 |
:enabled |
$(":enabled") |
所有激活的input 元素 |
:disabled |
$(":disabled") |
所有禁用的input 元素 |
:selected |
$(":selected") |
所有被選取的input 元素 |
:checked |
$(":checked") |
所有被選中的input 元素 |
Chap3-65-html
<head><script src=“js/jquery-3.3.1.js”></script>
<style> .s1{display: inline-block;width: 80px;height:40px;font-size: x-large}
.s2{display: inline-block;width: 200px;height:40px;font-size: x-large}
</style></head>
<body>
<pre>
<span class=“s1”>用戶名:</span><span class=“s2”><input type=“text”></span>
<span class=“s1”>密碼:</span><span class=“s2”><input type=“password”></span>
<span class=“s1”>性別:</span><span class=“s2”><input type=“radio” name=“sex” checked>男 <input type=“radio” name=“sex”>女</span>
<button>加邊框</button>
</pre>
<script>
$(document).ready(function () {
$(":text").css("background-color","lightgray");
$(":password").css("color","red");
$(":button").click(function () {
$(":checked").css("outline","dotted medium green");
});
});
</script>
</body>
事件
事件方法 | 描述 |
---|---|
$(document).ready(function) |
將函數(shù)綁定到文檔的就緒事件(當(dāng)文檔完成加載時(shí)) |
$(selector).click(function) |
觸發(fā)或?qū)⒑瘮?shù)綁定到被選元素的點(diǎn)擊事件 |
$(selector).dblclick(function) |
觸發(fā)或?qū)⒑瘮?shù)綁定到被選元素的雙擊事件 |
$(selector).focus(function) |
觸發(fā)或?qū)⒑瘮?shù)綁定到被選元素的獲得焦點(diǎn)事件 |
$(selector).mouseover(function) |
觸發(fā)或?qū)⒑瘮?shù)綁定到被選元素的鼠標(biāo)懸停事件 |
$(selector).mouseleave(function) |
觸發(fā)或?qū)⒑瘮?shù)綁定到被選元素的mouse leave事件 |
$(selector).change(function) |
觸發(fā)或?qū)⒑瘮?shù)綁定到被選元素的change事件 |
$(selector).keydown(function) |
觸發(fā)或?qū)⒑瘮?shù)綁定到被選元素的key down事件 |
$(selector).keyup(function) |
觸發(fā)或?qū)⒑瘮?shù)綁定到被選元素的key up事件 |
Chap3-66.html
<head><script src="js/jquery-3.3.1.js"></script>
<style>.s1{display: inline-block;width: 80px;height:40px;font-size: x-large}
.s2{display: inline-block;width: 200px;height:40px;font-size: x-large}
.outline{outline: medium dotted green}</style></head>
<body>
<pre>
<span class="s1">用戶名:</span><span class="s2"><input type="text"></span>
<span class="s1">密碼:</span><span class="s2"><input type="password"></span>
<span class="s1">性別:</span><span class="s2"><input type="radio" name="sex" checked>男 <input type="radio" name="sex">女</span>
</pre>
<script>
$(document).ready(function () {
$(":text").keydown(function () {$(this).css("background-color","lightgreen");});
$(":text").keyup(function () {$(this).css("background-color","lightgray");});
$(":password").dblclick(function () {$(this).hide();});
$(":radio").mousemove(function () {$(this).addClass("outline");});
$(":radio").mouseleave(function () {$(this).removeClass("outline");});
});
</script>
效果
方法 | 描述 |
---|---|
animate() |
對被選元素應(yīng)用“自定義”的動(dòng)畫 |
clearQueue() |
對被選元素移除所有排隊(duì)的函數(shù)(仍未運(yùn)行的) |
delay() |
對被選元素的所有排隊(duì)函數(shù)(仍未運(yùn)行)設(shè)置延遲 |
dequeue() |
運(yùn)行被選元素的下一個(gè)排隊(duì)函數(shù) |
fadeIn() |
逐漸改變被選元素的不透明度,從隱藏到可見 |
fadeOut() |
逐漸改變被選元素的不透明度取刃,從可見到隱藏 |
fadeTo() |
把被選元素逐漸改變至給定的不透明度 |
hide() |
隱藏被選的元素 |
queue() |
顯示被選元素的排隊(duì)函數(shù) |
show() |
顯示被選的元素 |
slideDown() |
通過調(diào)整高度來滑動(dòng)顯示被選元素 |
slideToggle() |
對被選元素進(jìn)行滑動(dòng)隱藏和滑動(dòng)顯示的切換 |
slideUp() |
通過調(diào)整高度來滑動(dòng)隱藏被選元素 |
stop() |
停止在被選元素上運(yùn)行動(dòng)畫 |
toggle() |
對被選元素進(jìn)行隱藏和顯示的切換 |
-
animate()
方法執(zhí)行CSS屬性集的自定義動(dòng)畫蹋肮。該方法通過CSS樣式將元素從一個(gè)狀態(tài)改變?yōu)榱硪粋€(gè)狀態(tài)。CSS屬性值是逐漸改變的璧疗,這樣就可以創(chuàng)建動(dòng)畫效果坯辩。語法:
$(selector).animate(styles,speed,easing,callback)
參數(shù) 說明 styles
必需。規(guī)定產(chǎn)生動(dòng)畫效果的 CSS 樣式和值崩侠。 可能的 CSS 樣式值: backgroundPosition
漆魔、borderWidth
、borderBottomWidth
啦膜、borderLeftWidth
有送、orderRightWidth
堰汉、borderTopWidth
盟猖、borderSpacing
鼻吮、margin
腥放、marginBottom
重慢、marginLeft
兔辅、marginRight
数初、marginTop
鹤啡、outlineWidth
、padding
清蚀、paddingBottom
匕荸、paddingLeft
、paddingRight
枷邪、paddingTop
榛搔、height
、width
东揣、maxHeight
践惑、maxWidth
、minHeight
嘶卧、minWidth
尔觉、font
、fontSize
芥吟、bottom
侦铜、left
、right
钟鸵、top
钉稍、letterSpacing
、wordSpacing
携添、lineHeight
嫁盲、textIndent
speed
可選。規(guī)定動(dòng)畫的速度烈掠。默認(rèn)是 normal
羞秤。可能的值:毫秒(比如1500
)左敌、slow
瘾蛋、normal
、fast
easing
可選矫限。規(guī)定在不同的動(dòng)畫點(diǎn)中設(shè)置動(dòng)畫速度的 easing
函數(shù)哺哼。內(nèi)置的easing
函數(shù):swing
、linear
callback
可選叼风。 animate
函數(shù)執(zhí)行完之后取董,要執(zhí)行的函數(shù)。注意:只有數(shù)字值可創(chuàng)建動(dòng)畫(比如
margin:30px
)无宿。字符串值無法創(chuàng)建動(dòng)畫(比如background-color:red
)茵汰。 -
delay()
方法對被選元素的所有排隊(duì)函數(shù)(仍未運(yùn)行)設(shè)置延遲。如果當(dāng)前動(dòng)畫還沒執(zhí)行完孽鸡,并不會(huì)立即停止蹂午,而是等當(dāng)前動(dòng)畫執(zhí)行完栏豺,然后延遲,再執(zhí)行下一個(gè)動(dòng)畫豆胸。它常用在隊(duì)列中的兩個(gè)jQuery效果函數(shù)之間奥洼,從而在上一個(gè)動(dòng)畫效果執(zhí)行后,延遲指定時(shí)間晚胡,然后再執(zhí)行下一個(gè)動(dòng)畫灵奖。語法:
$(selector).delay(duration,[queueName])
參數(shù) 說明 duration
延時(shí)時(shí)間,單位:毫秒 queueName
隊(duì)列名詞估盘,默認(rèn)是 Fx
桑寨,動(dòng)畫隊(duì)列。 -
queue()
方法顯示或操作在匹配元素上執(zhí)行的函數(shù)隊(duì)列忿檩。隊(duì)列是一個(gè)或多個(gè)等待運(yùn)行的函數(shù)。queue()
方法通常與dequeue()
方法一起使用爆阶。語法:
$(selector).queue(queueName)
-
dequeue()
方法為匹配元素執(zhí)行序列中的下一個(gè)函數(shù)燥透。當(dāng)調(diào)用.dequeue()
時(shí),會(huì)從序列中刪除下一個(gè)函數(shù)辨图,然后執(zhí)行它班套。該函數(shù)反過來會(huì)(直接或間接地)引發(fā)對.dequeue()
的調(diào)用,這樣序列才能繼續(xù)下去故河。語法:
$(selector).dequeue(queueName)
注意:當(dāng)通過
.queue()
添加函數(shù)時(shí)吱韭,我們應(yīng)當(dāng)確保最終調(diào)用了.dequeue()
,這樣下一個(gè)排隊(duì)的函數(shù)才能執(zhí)行鱼的。Chap3-68.html
<body> <button id="start">開始動(dòng)畫</button><button id="stop">停止動(dòng)畫</button> <div style="background-color: green;height: 100px;width: 100px;position: absolute"></div> <script> $(document).ready(function () { var div=$("div"); $("#start").click(function () { div.animate({height:"300px",opacity:"0.4"},"slow"); div.animate({width:"300px",opacity:"0.8"},"slow"); div.queue(function () { div.css("background-color","red"); div.dequeue(); }) div.animate({height:"100px",opacity:"0.4"},"slow"); div.animate({width:"100px",opacity:"0.8"},"slow"); div.delay(1000).animate({width:"500px",opacity:"0.4"}); }); $("#stop").click(function () { div.clearQueue(); }); }); </script> </body>
-
fadeIn()
方法使用淡入效果來顯示被選元素理盆,假如該元素是隱藏的。語法:
$(selector).fadeIn(speed,callback)
參數(shù) 說明 speed
可選凑阶。規(guī)定元素從隱藏到可見的速度猿规。默認(rèn)為 normal
≈娉鳎可能的值:毫秒 (比如1500
)姨俩、slow
、normal
师郑、fast
环葵。在設(shè)置速度的情況下,元素從隱藏到可見的過程中宝冕,會(huì)逐漸地改變其透明度(這樣會(huì)創(chuàng)造淡入效果)张遭。callback
可選。 fadeIn
函數(shù)執(zhí)行完之后猬仁,要執(zhí)行的函數(shù)帝璧。除非設(shè)置了speed
參數(shù)先誉,否則不能設(shè)置該參數(shù)。 -
fadeOut()
方法使用淡出效果來隱藏被選元素的烁,假如該元素是顯示的褐耳。語法:
$(selector).fadeOut(speed,callback)
-
fadeTo()
方法將被選元素的不透明度逐漸地改變?yōu)橹付ǖ闹怠?/p>語法:
$(selector).fadeTo(speed,opacity,callback)
參數(shù) 說明 opacity
必需。規(guī)定要淡入或淡出的透明度渴庆。必須是介于 0.00
與1.00
之間的數(shù)字铃芦。Chap3-68.html
<button id="fadeout">淡出</button><button id="fadein">淡入</button> <button id="fadeto">改變透明度</button> <div style="background-color: green;height: 100px;width: 100px;position: absolute"></div> <script> $(document).ready(function () { var div=$("div"); $("#fadein").click(function () { div.fadeIn(1000,function () { alert("fadeIn()方法已完成!"); }); }); $("#fadeout").click(function () { div.fadeOut(1000,function () { alert("fadeOut()方法已完成襟雷!"); }); }); $("#fadeto").click(function () { div.fadeTo(2000,0.4,function () { alert("fadeTo()方法已完成刃滓!"); }); });
-
hide()
方法如果被選的元素已被顯示,則隱藏該元素耸弄。語法:
$(selector).hide(speed,callback)
-
show()
方法如果被選元素已被隱藏咧虎,則顯示這些元素。語法:
$(selector).show(speed,callback)
-
slideDown()
方法通過使用滑動(dòng)效果计呈,顯示隱藏的被選元素砰诵。語法:
$(selector).slideDown(speed,callback)
-
slideUp()
方法通過使用滑動(dòng)效果,隱藏被選元素捌显,如果元素已顯示出來的話茁彭。語法:
$(selector).slideUp(speed,callback)
-
slideToggle()
方法通過使用滑動(dòng)效果(高度變化)來切換元素的可見狀態(tài)。如果被選元素是可見的扶歪,則隱藏這些元素理肺,如果被選元素是隱藏的,則顯示這些元素善镰。語法:
$(selector).slideToggle(speed,callback)
Chap3-68.html
<button id="hide">隱藏</button><button id="show">顯示</button><button id="slidedown">Slide Down</button> <button id="slideup">Slide Up</button><button id="slidetoggle">Slide Toggle</button> <div style="background-color: green;height: 100px;width: 100px;position: absolute"></div>
$(document).ready(function () { var div=$("div"); $("#hide").click(function () { div.hide(1000); }); $("#show").click(function () { div.show(1000,function () { div.css("background-color","blue"); }); }); $("#slidedown").click(function () { div.slideDown(1000); }); $("#slideup").click(function () { div.slideUp(1000); }); $("#slidetoggle").click(function () { div.slideToggle(1000); }); });
文檔操作
方法 | 描述 |
---|---|
addClass() |
向匹配的元素添加指定的類名妹萨。 |
after() |
在匹配的元素之后插入內(nèi)容。 |
append() |
向匹配元素集合中的每個(gè)元素結(jié)尾插入由參數(shù)指定的內(nèi)容媳禁。 |
appendTo() |
向目標(biāo)結(jié)尾插入匹配元素集合中的每個(gè)元素眠副。 |
attr() |
設(shè)置或返回匹配元素的屬性和值。 |
before() |
在每個(gè)匹配的元素之前插入內(nèi)容竣稽。 |
clone() |
創(chuàng)建匹配元素集合的副本囱怕。 |
detach() |
從DOM中移除匹配元素集合。 |
empty() |
刪除匹配的元素集合中所有的子節(jié)點(diǎn)毫别。 |
hasClass() |
檢查匹配的元素是否擁有指定的類娃弓。 |
html() |
設(shè)置或返回匹配的元素集合中的HTML內(nèi)容宣蔚。 |
insertAfter() |
把匹配的元素插入到另一個(gè)指定的元素集合的后面崎逃。 |
insertBefore() |
把匹配的元素插入到另一個(gè)指定的元素集合的前面。 |
prepend() |
向匹配元素集合中的每個(gè)元素開頭插入由參數(shù)指定的內(nèi)容戴而。 |
prependTo() |
向目標(biāo)開頭插入匹配元素集合中的每個(gè)元素。 |
remove() |
移除所有匹配的元素挽霉。 |
removeAttr() |
從所有匹配的元素中移除指定的屬性防嗡。 |
removeClass() |
從所有匹配的元素中刪除全部或者指定的類。 |
replaceAll() |
用匹配的元素替換所有匹配到的元素侠坎。 |
replaceWith() |
用新內(nèi)容替換匹配的元素蚁趁。 |
text() |
設(shè)置或返回匹配元素的內(nèi)容。 |
toggleClass() |
從匹配的元素中添加或刪除一個(gè)類实胸。 |
unwrap() |
移除并替換指定元素的父元素他嫡。 |
val() |
設(shè)置或返回匹配元素的值。 |
wrap() |
把匹配的元素用指定的內(nèi)容或元素包裹起來庐完。 |
wrapAll() |
把所有匹配的元素用指定的內(nèi)容或元素包裹起來钢属。 |
wrapinner() |
將每一個(gè)匹配的元素的子內(nèi)容用指定的內(nèi)容或元素包裹起來。 |
-
addClass()
方法向被選元素添加一個(gè)或多個(gè)類门躯。該方法不會(huì)移除已存在的class
屬性淆党,僅僅添加一個(gè)或多個(gè)class
屬性。語法:
$(selector).addClass(class)
-
hasClass()
方法檢查被選元素是否包含指定的 class讶凉。語法:
$(selector).hasClass(class)
-
removeClass()
方法從被選元素移除一個(gè)或多個(gè)類宁否。如果沒有規(guī)定參數(shù),則該方法將從被選元素中刪除所有類缀遍。語法:
$(selector).removeClass(class)
-
toggleClass()
對設(shè)置或移除被選元素的一個(gè)或多個(gè)類進(jìn)行切換。語法:
$(selector).toggleClass(class,switch)
參數(shù) 說明 switch
可選饱须。布爾值域醇。規(guī)定是否添加或移除class。 Chap3-69.html
<head><script src="js/jquery-3.3.1.js"></script>? <style>? .intro{font-size: x-large;color: blue} .note{background-color: yellow} .main{color:red}? </style>?</head>?<body>?<h1>This is a heading</h1><p>This is a paragraph.</p><p>This is another paragraph.</p>?<button id="btn1">向第一個(gè) p 元素添加兩個(gè)類</button><button id="btn2">改變第一個(gè)段落的類</button>?<button id="btn3">切換段落的 "main" 類</button>?<script>? $(document).ready(function(){? $("#btn1").click(function(){? $("p:first").addClass("intro note");? });? $("#btn2").click(function(){? $("p:first").removeClass("intro").addClass("main");? });? $("#btn3").click(function(){? $("p:first ").toggleClass("main");? });? });?</script>
-
after()
方法在被選元素后插入指定的內(nèi)容蓉媳。語法:
-
append()
方法在被選元素的結(jié)尾(仍然在內(nèi)部)插入指定內(nèi)容譬挚。語法:
$(selector).append(content)
-
appendTo()
方法在被選元素的結(jié)尾(仍然在內(nèi)部)插入指定內(nèi)容,規(guī)定要插入的內(nèi)容必須包含 HTML 標(biāo)簽。語法:
$(content).appendTo(selector)
-
before()
方法在被選元素前插入指定的內(nèi)容酪呻。語法:
$(selector).before(content)
-
prepend()
方法在被選元素的開頭(仍位于內(nèi)部)插入指定內(nèi)容减宣。語法:
$(selector).prepend(content)
-
prependTo()
方法在被選元素的開頭(仍位于內(nèi)部)插入指定內(nèi)容,規(guī)定要插入的內(nèi)容必須包含HTML標(biāo)簽。語法:
$(content).prependTo(selector)
-
insertBefore()
方法在被選元素之前插入HTML標(biāo)記或已有的元素,規(guī)定要插入的內(nèi)容必須包含HTML標(biāo)簽玩荠。語法:
$(content).insertBefore(selector)
-
insertAfter()
方法在被選元素之后插入HTML標(biāo)記或已有的元素,規(guī)定要插入的內(nèi)容必須包含HTML標(biāo)簽漆腌。語法:
$(content).insertAfter(selector)
**Chap3-69.html **
<button id="btn4">after插入內(nèi)容</button> <button id="btn5">append插入內(nèi)容</button> <button id="btn6">appendTo插入內(nèi)容</button> <button id="btn7">before插入內(nèi)容</button> <button id="btn8">prepend插入內(nèi)容</button> <button id="btn9">prependTo插入內(nèi)容</button> <button id="btn10">insertBefore插入內(nèi)容</button> <button id="btn11">insertAfter插入內(nèi)容</button> <script> $(document).ready(function(){ $("#btn4").click(function(){$("p:first").after("Hello World!"); }); $("#btn5").click(function(){$("p:eq(1)").append("Hello World!"); }); $("#btn6").click(function(){$("<b> Hello World!</b>").appendTo("p:eq(1)");}); $("#btn7").click(function(){$("p:first").before("Hello World!");}); $("#btn8").click(function(){$("p:eq(1)").prepend("Hello World!");}); $("#btn9").click(function(){$("<b> Hello World!</b>").prependTo("p:eq(1)");}); $("#btn10").click(function(){$("<b> 你好!</b>").insertBefore("p:eq(1)");}); $("#btn11").click(function(){$("<b> 你好!</b>").insertAfter("p:eq(1)");}); });
-
attr()
方法設(shè)置或返回被選元素的屬性和值。當(dāng)該方法用于返回屬性值阶冈,則返回第一個(gè)匹配元素的值闷尿。當(dāng)該方法用于設(shè)置屬性值,則為匹配元素設(shè)置一個(gè)或多個(gè)屬性/值對女坑。- 返回屬性的值:
$(selector).attr(attribute)
- 設(shè)置屬性和值:
$(selector).attr(attribute,value)
- 使用函數(shù)設(shè)置屬性和值:
$(selector).attr(attribute,function(index,currentvalue))
- 設(shè)置多個(gè)屬性和值:
$(selector).attr({attribute:value, attribute:value,...})
參數(shù) 描述 attribute
規(guī)定屬性的名稱填具。 value
規(guī)定屬性的值。 function(index,currentvalue)
規(guī)定要返回屬性值到集合的函數(shù) : index
接受集合中元素的index位置匆骗;currentvalue
接受被選元素的當(dāng)前屬性值劳景。Chap3-69.html
<p><img src="pic/apple.jpg" alt="red apple" width="284" height="213"></p> <button id="btn12">返回圖片的寬度</button> <button id="btn13">圖像寬度減少50 px</button> <button id="btn14">給圖片設(shè)置寬度和高度屬性</button> <script> $(document).ready(function(){ $("#btn12").click(function(){alert("圖片寬度: " + $("img").attr("width"));}); $("#btn13").click(function(){ $("img").attr("width",function (n,v) { return v-50; }) }); $("#btn14").click(function(){$("img").attr({width:"150",height:"100"});}); });
- 返回屬性的值:
-
removeAttr()
方法從被選元素移除一個(gè)或多個(gè)屬性誉简。語法:
$(selector).removeAttr(attribute)
-
html()
方法設(shè)置或返回被選元素的內(nèi)容(innerHTML)。當(dāng)該方法用于返回內(nèi)容時(shí)盟广,則返回第一個(gè)匹配元素的內(nèi)容闷串。當(dāng)該方法用于設(shè)置內(nèi)容時(shí),則重寫所有匹配元素的內(nèi)容衡蚂。- 返回內(nèi)容:
$(selector).html()
- 設(shè)置內(nèi)容:
$(selector).html(content)
- 使用函數(shù)設(shè)置內(nèi)容:
$(selector).html(function(index,currentcontent))
- 返回內(nèi)容:
-
text()
方法設(shè)置或返回被選元素的文本內(nèi)容窿克。當(dāng)該方法用于返回內(nèi)容時(shí),則返回所有匹配元素的文本內(nèi)容(會(huì)刪除HTML標(biāo)記)毛甲。當(dāng)該方法用于設(shè)置內(nèi)容時(shí)年叮,則重寫所有匹配元素的內(nèi)容。- 返回文本內(nèi)容:
$(selector).text()
- 設(shè)置文本內(nèi)容:
$(selector).text(content)
- 使用函數(shù)設(shè)置文本內(nèi)容:
$(selector).text(function(index,currentcontent))
Chap3-69.html
<p class="main note">這是<b>另一個(gè)</b>段落玻募。</p> <button id="btn15">刪除所有 p 元素的 style 屬性</button> <button id="btn16">html()修改第四個(gè)段落的內(nèi)容</button> <button id="btn17">text()修改第四個(gè)段落的內(nèi)容</button> <script> $(document).ready(function(){ $("#btn15").click(function(){$("p").removeAttr("class");}); $("#btn16").click(function(){ $("p").html(function(n){ if(n===3){return $(this).html()+"這個(gè)P元素的索引位置為: " + n;} }); }); $("#btn17").click(function(){ $("p:eq(3)").text(function(n){return $(this).text();}); }); });
- 返回文本內(nèi)容:
-
val()
方法返回或設(shè)置被選元素的value
屬性只损。當(dāng)用于返回值時(shí):該方法返回第一個(gè)匹配元素的 value 屬性的值。當(dāng)用于設(shè)置值時(shí):該方法設(shè)置所有匹配元素的value
屬性的值七咧。- 返回
value
屬性:$(selector).val()
- 設(shè)置
value
屬性:$(selector).val(value)
- 通過函數(shù)設(shè)置
value
屬性:$(selector).val(function(index,currentvalue))
- 返回
-
replaceWith() 和replaceAll()方法用指定的 HTML 內(nèi)容或元素替換被選元素跃惫。差異在于語法:內(nèi)容和選擇器的位置,以及 replaceWith() 能夠使用函數(shù)進(jìn)行替換艾栋。
語法:
$(selector).replaceWith(content) $(content).replaceAll(selector)
-
wrap()方法把每個(gè)被選元素放置在指定的 HTML 內(nèi)容或元素中爆存。
語法:
$(selector).wrap(wrappingElement,function(index))
參數(shù) 描述 wrappingElement
必需。規(guī)定包裹每個(gè)被選元素的HTML元素蝗砾∠冉希可能的值: HTML元素、jQuery對象悼粮、DOM 元素 function(index)
可選闲勺。規(guī)定返回包裹元素的函數(shù)。 index
:返回集合中元素的index
位置扣猫。 -
unwrap()方法移除被選元素的父元素菜循。
語法:
$(selector).unwrap()
Chap3-69.html
<style> div{border: medium dotted black;width: 800px} </style> <p>姓名: <input type="text" name="fname" value="Peter"></p> <button id="btn18">返回第一個(gè)輸入字段的值</button> <button id="btn19">設(shè)置姓名的值</button> <button id="btn20">替換每個(gè)P元素</button> <button id="btn21">創(chuàng)建一個(gè)新的div來環(huán)繞每個(gè)p元素</button> <button id="btn22">去掉 div 元素</button>
$(document).ready(function(){ $("#btn18").click(function(){$("p:eq(3)").text($("input:text").val());}); $("#btn19").click(function(){ $("input:text").val(function (n,c) { return c+" Chen"; }); }); $("#btn20").click(function(){ $("p").replaceWith(function(n){ return "<h3>這個(gè)元素的下標(biāo)是 " + n + ".</h3>"; }); }); $("#btn21").click(function(){$("p").wrap(document.createElement("div"));}); $("#btn22").click(function(){$("p").unwrap();});
CSS操作
css()
方法為被選元素設(shè)置或返回一個(gè)或多個(gè)樣式屬性。
當(dāng)用于返回屬性:
- 該方法返回第一個(gè)匹配元素的指定CSS屬性值申尤。然而癌幕,簡寫的CSS屬性(比如
background
和border
)不被完全支持,且當(dāng)用于返回屬性值時(shí)昧穿,在不同的瀏覽器中有不同的結(jié)果序芦。 - 語法:
$(selector).css(property)
當(dāng)用于設(shè)置屬性:
- 該方法為所有匹配元素設(shè)置指定CSS屬性。
- 設(shè)置CSS屬性和值:
$(selector).css(property,value)
- 使用函數(shù)設(shè)置CSS屬性和值:
$(selector).css(property,function(index,currentvalue))
- 設(shè)置多個(gè)屬性和值:
$(selector).css({屬性:value, 屬性:value, ...})
Chap3-70.html
<body><p style="font-size: 30px;color: red">這是一個(gè)段落粤咪。</p>
<button id=“btn1”>返回P元素的CSS樣式顏色值</button><button id=“btn2”>設(shè)置P元素的字體大小</button>
<button id="btn3">設(shè)置P元素的多個(gè)css屬性</button>
<script>
$(document).ready(function(){
$("#btn1").click(function(){$("p").text($("p").css("color"));});
$("#btn2").click(function(){
$("p").css("font-size",function(i,v){
return Number(v.substr(0,v.length-2))+10;
});
});
$("#btn3").click(function(){
$("p").css({
"color":"white",
"background-color":"lightgray",
"font-family":"Arial",
"font-size":"50px",
"padding":"5px"
});
});
});
</script>
</body>
客戶端存儲(chǔ)
客戶端存儲(chǔ)web應(yīng)用允許使用瀏覽器提供的API實(shí)現(xiàn)將數(shù)據(jù)存儲(chǔ)在用戶電腦上谚中。
客戶端存儲(chǔ)遵循"同源策略",因此不同站點(diǎn)的頁面是無法讀取對于存儲(chǔ)的數(shù)據(jù)。而同一站點(diǎn)的不同的頁面之間是可以互相共享存儲(chǔ)數(shù)據(jù)的宪塔。
web應(yīng)用可以選擇他們存儲(chǔ)數(shù)據(jù)的有效期:有臨時(shí)存儲(chǔ)的磁奖,可以讓數(shù)據(jù)保存至當(dāng)前窗口關(guān)閉或?yàn)g覽器退出;也有永久存儲(chǔ)某筐,可以將數(shù)據(jù)永久地存儲(chǔ)在硬盤上比搭,數(shù)年或者數(shù)月不失效。
客戶端存儲(chǔ)有以下幾種形式:
-
web存儲(chǔ)
先是HTML5的一個(gè)API南誊,后來成了標(biāo)準(zhǔn)了身诺。目前包含IE8在內(nèi)的主流瀏覽器都實(shí)現(xiàn)了。包含localStorage和sessionStorage對象抄囚,這兩個(gè)對象實(shí)際上是持久化的關(guān)聯(lián)數(shù)組霉赡,是名值對的映射表,“名”和“值”都是字符串幔托。web存儲(chǔ)易于使用穴亏,支持大容量(但非無限量)數(shù)據(jù)存儲(chǔ),同時(shí)兼容當(dāng)前所有主流瀏覽器重挑。
-
cookie
cookie是一種早期的客戶端存儲(chǔ)機(jī)制嗓化,起初是針對服務(wù)器端腳本設(shè)計(jì)使用的。盡管在客戶端提供了非常繁瑣的javascript API來操作cookie谬哀,但它們難用至極刺覆,而且只適合少量的文本存儲(chǔ)。不僅如此史煎,任何以cookie形式存儲(chǔ)的數(shù)據(jù)隅津,不論服務(wù)器端是否需要,每一次HTTP請求都要把這些數(shù)據(jù)傳輸?shù)椒?wù)器端劲室。cookie目前仍然被大量的客戶端程序員使用的一個(gè)重要的原因是:所有新舊瀏覽器都支持它。但是结窘,隨著Web Storage的普及很洋,cookie將最終回歸到最初的形態(tài):作為一種被服務(wù)端腳本使用的客戶存儲(chǔ)機(jī)制。
Web存儲(chǔ)
實(shí)現(xiàn)了“web存儲(chǔ)”草案標(biāo)準(zhǔn)的瀏覽器在window對象上定義了兩個(gè)屬性隧枫,localStorage和sessionStorage喉磁。在控制臺(tái)輸入window.localStorage
可以獲得頁面所存儲(chǔ)的數(shù)據(jù)。
這兩個(gè)屬性代表同一個(gè)Storage對象(一個(gè)持久化關(guān)聯(lián)數(shù)組)官脓,數(shù)組使用字符串來索引协怒,存儲(chǔ)的值也是字符串形式的,Storage對象在使用上和一般的Javascript沒有什么兩樣卑笨,設(shè)置對象的屬性為字符串值孕暇,隨后瀏覽器會(huì)將值存儲(chǔ)起來。lcoalStorage和sessionStorage兩者的區(qū)別在于存儲(chǔ)的有效期和作用域不同:即數(shù)據(jù)可以存儲(chǔ)多長時(shí)間以及誰擁有數(shù)據(jù)的訪問權(quán)。
通過localStorage存儲(chǔ)的數(shù)據(jù)是永久性的妖滔,除非web應(yīng)用立刻刪除存儲(chǔ)的數(shù)據(jù)隧哮。或者用戶通過設(shè)置瀏覽器配置來刪除桦沉,否則數(shù)據(jù)將一直保留在用戶電腦上措左,永不過期秕磷。
localStorage的作用域是限定在文檔源(document origin)級(jí)別的。文檔源是通過協(xié)議采蚀、主機(jī)名及端口三者來確定的。因此承二,每個(gè)url都有不同的文檔源榆鼠。
sessionStorage的有效期與存儲(chǔ)數(shù)據(jù)的腳本所在最頂層的窗口或者是瀏覽器標(biāo)簽頁是一樣的。一旦窗口或者標(biāo)簽頁被永久關(guān)閉了矢洲,那么所有通過sessionStorage存儲(chǔ)的數(shù)據(jù)也被刪除了璧眠。
sessionStorage的作用域也是限定在文檔源中,因此读虏,非同源的文檔之間是無法貢獻(xiàn)sessionStorage的责静。不僅如此,sessionStorage的作用域還被限定在窗口中盖桥。如果同源的文檔渲染在不同的瀏覽器標(biāo)簽頁中灾螃,那么他們互相之間擁有的是各自的sessionStorage數(shù)據(jù),無法共享揩徊。就是說腰鬼,同個(gè)瀏覽器下兩個(gè)相同的標(biāo)簽頁也不能共享數(shù)據(jù)。
Chap3-71.html
<p>中文姓名:<input type="text" id="txtC"> </p><p>英文姓名:<input type="text" id="txtE"> </p>
<button id="btn1">Web存儲(chǔ)-localStorage</button><button id="btn2">Web存儲(chǔ)-sessionStorage</button>
$(document).ready(function(){
var nameC=localStorage.uNameC; //等同于nameC=localStorage["unameC"]
if(!nameC){
$("#txtC").val("請輸入用戶名");
}else{
$("#txtC").val(localStorage.uNameC);
}
var nameE=sessionStorage.uNameE;
if(!nameE){
$("#txtE").val("Please input your name");
}else{
$("#txtE").val(sessionStorage.uNameE);
}
$("#btn1").click(function(){
localStorage.uNameC=$("#txtC").val();
});
$("#btn2").click(function(){
sessionStorage.uNameE=$("#txtE").val();
});
});
localStorage和sessionStorage通常是被當(dāng)做普通的javascript對象使用塑荒。通過設(shè)置屬性來存儲(chǔ)字符串值熄赡,查詢該屬性來讀取該值。這兩個(gè)對象還提供了一些屬性和方法:
屬性或方法 | 語法 | 說明 |
---|---|---|
length |
Storage.length |
返回存儲(chǔ)在Storage 對象里的數(shù)據(jù)項(xiàng)數(shù)量齿税。 |
setItem() |
storage.setItem(keyName, keyValue); |
接受一個(gè)鍵名和值作為參數(shù)彼硫,將會(huì)把鍵名添加到存儲(chǔ)中,如果鍵名已存在凌箕,則更新其對應(yīng)的值拧篮。 |
getItem() |
storage.getItem(keyName); |
接受一個(gè)鍵名作為參數(shù),并返回對應(yīng)鍵名的值牵舱。 |
removeItem() |
storage.removeItem(keyName); |
接受一個(gè)鍵名作為參數(shù)串绩,會(huì)把該鍵名從存儲(chǔ)中移除。 |
clear() |
storage.clear(); |
調(diào)用它可以清空存儲(chǔ)對象里所有的鍵值芜壁。 |
key() |
storage.key(key); |
接受一個(gè)數(shù)值n 作為參數(shù)礁凡,返回存儲(chǔ)對象第n 個(gè)數(shù)據(jù)項(xiàng)的鍵名高氮。 |
Chap3-71.html
<div id="results" style="font-size: x-large"></div>
$(document).ready(function(){
localStorage.setItem('bgcolor', 'red');
localStorage.setItem('font', 'Helvetica');
localStorage.setItem('image', 'myCat.png');
$("#results").html("刪除前Storage中數(shù)據(jù)項(xiàng):<br>");
for(var i=0;i<localStorage.length;i++){
$("#results").html(function (n,v) {
return v+localStorage.key(i)+": "+localStorage.getItem(localStorage.key(i))+"<br>";
});
}
localStorage.removeItem("image");
$("#results").html(function (n,v) {
return v+"刪除后Storage中數(shù)據(jù)項(xiàng):<br>";
});
for(var i=0;i<localStorage.length;i++){
$("#results").html(function (n,v) {
return v+localStorage.key(i)+": "+localStorage.getItem(localStorage.key(i))+"<br>";
});
}
});
$(document).ready(function(){
localStorage.setItem('bgcolor', 'red');
localStorage.setItem('font', 'Helvetica');
localStorage.setItem('image', 'myCat.png');
$("#results").html("刪除前Storage中數(shù)據(jù)項(xiàng):<br>");
for(var i=0;i<localStorage.length;i++){
$("#results").html(function (n,v) {
return v+localStorage.key(i)+": "+localStorage.getItem(localStorage.key(i))+"<br>";
});
}
localStorage.removeItem("image");
$("#results").html(function (n,v) {
return v+"刪除后Storage中數(shù)據(jù)項(xiàng):<br>";
});
for(var i=0;i<localStorage.length;i++){
$("#results").html(function (n,v) {
return v+localStorage.key(i)+": "+localStorage.getItem(localStorage.key(i))+"<br>";
});
}
});
cookie
cookie是指web瀏覽器存儲(chǔ)的少量數(shù)據(jù),同時(shí)它是與具體的web頁面或者站點(diǎn)相關(guān)的把篓。cookie最早是設(shè)計(jì)為被服務(wù)端所用的纫溃,cookie數(shù)據(jù)會(huì)自動(dòng)在web瀏覽器和web服務(wù)器之間傳輸,因此服務(wù)端腳本就可以讀韧掩、寫客戶端的cookie值紊浩。
可以通過document.cookie
來獲取cookie值。詳見3.2.1.3疗锐。
JSON
什么是JSON坊谁?
JSON 指的是 JavaScript 對象表示法(JavaScript Object Notation)。
JSON 是輕量級(jí)的文本數(shù)據(jù)交換格式滑臊。
JSON 使用JavaScript語法來描述數(shù)據(jù)對象口芍,但是JSON仍然獨(dú)立于語言和平臺(tái)。JSON解析器和JSON庫支持許多不同的編程語言雇卷。
JSON 具有自我描述性鬓椭,更易理解。
JSON文件
JSON文件的文件類型是.json
关划。
JSON文本的 MIME 類型是application/json
小染。
JSON 語法規(guī)則
JSON 語法是 JavaScript 對象表示法語法的子集。
- 數(shù)據(jù)在名稱/值對中贮折。
- 數(shù)據(jù)由逗號(hào)分隔
- 花括號(hào)保存對象裤翩。
- 方括號(hào)保存數(shù)組。
{
"employees": [
{ "firstName":"Bill" , "lastName":"Gates" },
{ "firstName":"George" , "lastName":"Bush" },
{ "firstName":"Thomas" , "lastName":"Carter" }
]
}
可以像這樣訪問 JavaScript 對象數(shù)組中的第一項(xiàng):employees[0].lastName;
可以像這樣修改數(shù)據(jù):employees[0].lastName = "Jobs";
JSON 值可以是
- 數(shù)字(整數(shù)或浮點(diǎn)數(shù))
- 字符串(在雙引號(hào)中)
- 邏輯值(true 或 false)
- 數(shù)組(在方括號(hào)中)
- 對象(在花括號(hào)中)
- null
Chap3-72.html
<h2>在 JavaScript 中創(chuàng)建 JSON 對象</h2>
<p style="font-size: x-large">
Name: <span id="jname"></span><br />
Age: <span id="jage"></span><br />
Address: <span id="jstreet"></span><br />
Phone: <span id="jphone"></span><br />
</p>
<script type="text/javascript">
var JSONObject= {
"name":"Bill Gates",
"street":"Fifth Avenue New York 666",
"age":56,
"phone":"555 1234567"};
document.getElementById("jname").innerHTML=JSONObject.name;
document.getElementById("jage").innerHTML=JSONObject.age;
document.getElementById("jstreet").innerHTML=JSONObject.street;
document.getElementById("jphone").innerHTML=JSONObject.phone;
</script>
JSON的用法
JSON 最常見的用法之一调榄,是從web服務(wù)器上讀取JSON數(shù)據(jù)(作為文件或作為 HttpRequest)踊赠,將JSON數(shù)據(jù)轉(zhuǎn)換為JavaScript對象,然后在網(wǎng)頁中使用該數(shù)據(jù)每庆。
JavaScript 函數(shù)eval()
可用于將JSON文本轉(zhuǎn)換為JavaScript對象筐带。必須把文本包圍在括號(hào)中,這樣才能避免語法錯(cuò)誤:
var obj = eval ("(" + txt + ")");
提示:eval()
函數(shù)可編譯并執(zhí)行任何JavaScript代碼缤灵。這隱藏了一個(gè)潛在的安全問題伦籍。
使用JSON解析器將JSON轉(zhuǎn)換為JavaScript對象是更安全的做法。JSON解析器只能識(shí)別JSON文本凤价,而不會(huì)編譯腳本。
JSON對象和JSON字符串的轉(zhuǎn)換
-
JSON.parse(jsonString)
:在一個(gè)字符串中解析出JSON對象 -
jQuery.parseJSON(jsonString)
:將格式完好的JSON字符串轉(zhuǎn)為與之對應(yīng)的JavaScript對象 -
JSON.stringify(obj)
:將一個(gè)JSON對象轉(zhuǎn)換成字符串
JSON.parse()
和jQuery.parseJSON()
的區(qū)別:有的瀏覽器不支持JSON.parse()
方法拔创,使用jQuery.parseJSON()
方法時(shí)利诺,在瀏覽器支持時(shí)會(huì)返回執(zhí)行JSON.parse()
方法的結(jié)果,否則會(huì)返回類似執(zhí)行eval()
方法的結(jié)果剩燥。
Chap3-73.html
<h2>通過 JSON 字符串來創(chuàng)建對象</h3>
<p style="font-size: x-large">
First Name: <span id="fname1"></span><br />
Last Name: <span id="lname1"></span><br />
First Name: <span id="fname2"></span><br />
Last Name: <span id="lname2"></span><br />
</p>
<script type="text/javascript">
var txt = '{"employees":[' +
'{"firstName":"Bill","lastName":"Gates" },' +
'{"firstName":"George","lastName":"Bush" },' +
'{"firstName":"Thomas","lastName":"Carter" }]}';
var obj = eval ("(" + txt + ")");
document.getElementById("fname1").innerHTML=obj.employees[1].firstName;
document.getElementById("lname1").innerHTML=obj.employees[1].lastName;
var obj1 = JSON.parse(txt);
document.getElementById("fname2").innerHTML=obj1.employees[2].firstName;
document.getElementById("lname2").innerHTML=obj1.employees[2].lastName;
</script>
Node
- Node概述
- Node核心模塊
- Express框架
Node概述
Node慢逾,或者Node.js立倍,是一個(gè)可以讓JavaScript運(yùn)行在服務(wù)器端的平臺(tái)。因此侣滩,可以用Node.js輕松地進(jìn)行服務(wù)器端應(yīng)用開發(fā)口注,在服務(wù)端堪與PHP、Python君珠、Perl寝志、Ruby平起平坐。
使用 Node.js策添,你可以輕松地開發(fā):
- 具有復(fù)雜邏輯的網(wǎng)站材部;
- 基于社交網(wǎng)絡(luò)的大規(guī)模Web應(yīng)用;
- Web Socket服務(wù)器唯竹;
- TCP/UDP套接字應(yīng)用程序乐导;
- 命令行工具;
- 交互式終端程序浸颓;
- 帶有圖形用戶界面的本地應(yīng)用程序物臂;
- 單元測試工具;
- 客戶端JavaScript編譯器产上。
當(dāng)你使用Node.js時(shí)棵磷,不用額外搭建一個(gè) HTTP 服務(wù)器,因?yàn)镹ode.js本身就內(nèi)建了一個(gè)蒂秘。這個(gè)服務(wù)器不僅可以用來調(diào)試代碼泽本,而且它本身就可以部署到產(chǎn)品環(huán)境,它的性能足以滿足要求姻僧。
Node.js最大的特點(diǎn)就是采用異步式I/O與事件驅(qū)動(dòng)的架構(gòu)設(shè)計(jì)规丽。Node.js在執(zhí)行的過程中會(huì)維護(hù)一個(gè)事件隊(duì)列,程序在執(zhí)行時(shí)進(jìn)入事件循環(huán)等待下一個(gè)事件到來撇贺,每個(gè)異步式I/O請求完成后會(huì)被推送到事件隊(duì)列赌莺,等待程序進(jìn)程進(jìn)行處理。
例如松嘶,對于簡單而常見的數(shù)據(jù)庫查詢操作艘狭,按照傳統(tǒng)方式實(shí)現(xiàn)的代碼如下:
res = db.query('SELECT * from some_table');
res.output();
以上代碼在執(zhí)行到第一行的時(shí)候,線程會(huì)阻塞翠订,等待數(shù)據(jù)庫返回查詢結(jié)果巢音,然后再繼續(xù)處理。
對于高并發(fā)的訪問尽超,一方面線程長期阻塞等待官撼,另一方面為了應(yīng)付新請求而不斷增加線程,因此會(huì)浪費(fèi)大量系統(tǒng)資源似谁,同時(shí)線程的增多也會(huì)占用大量的CPU時(shí)間來處理內(nèi)存上下文切換傲绣,而且還容易遭受低速連接攻擊掠哥。
看看Node.js是如何解決這個(gè)問題的:
db.query('SELECT * from some_table', function(res) {
res.output();
});
//后面的語句
這段代碼中db.query
的第二個(gè)參數(shù)是一個(gè)函數(shù),我們稱為回調(diào)函數(shù)秃诵。進(jìn)程在執(zhí)行到db.query
的時(shí)候续搀,不會(huì)等待結(jié)果返回,而是直接繼續(xù)執(zhí)行后面的語句菠净,直到進(jìn)入事件循環(huán)禁舷。當(dāng)數(shù)據(jù)庫查詢結(jié)果返回時(shí),會(huì)將事件發(fā)送到事件隊(duì)列嗤练,等到線程進(jìn)入事件循環(huán)以后榛了,才會(huì)調(diào)用之前的回調(diào)函數(shù)繼續(xù)執(zhí)行后面的邏輯。
Node.js的異步機(jī)制是基于事件的煞抬,所有的磁盤I/O霜大、網(wǎng)絡(luò)通信、數(shù)據(jù)庫查詢都以非阻塞的方式請求革答,返回的結(jié)果由事件循環(huán)來處理俭驮。
Node.js進(jìn)程在同一時(shí)刻只會(huì)處理一個(gè)事件蛇尚,完成后立即進(jìn)入事件循環(huán)檢查并處理后面的事件。這樣做的好處是,CPU和內(nèi)存在同一時(shí)間集中處理一件事速那,同時(shí)盡可能讓耗時(shí)的I/O操作并行執(zhí)行朱沃。對于低速連接攻擊力九,Node.js只是在事件隊(duì)列中增加請求半火,等待操作系統(tǒng)的回應(yīng),因而不會(huì)有任何多線程開銷错沃,很大程度上可以提高Web應(yīng)用的健壯性栅组,防止惡意攻擊。
Chap4-1-1.js(異步讀取文件)
var fs=require('fs'); //內(nèi)置文件系統(tǒng)模塊fs
console.log("異步讀取文件");
fs.readFile('files/content.txt','utf-8',function (err,data) {
if(err){
console.error(err);
}else {
console.log(data);
}
});
console.log('end.');
Chap4-1-2.js(同步讀取文件)
var fs=require('fs'); //內(nèi)置文件系統(tǒng)模塊fs
console.log("同步讀取文件");
var data=fs.readFileSync('chap3.js','utf-8');
console.log(data);
console.log("end");
安裝
https://nodejs.org/en/網(wǎng)站上下載Node 8.11.1 LTS枢析,按步驟安裝即可玉掸。
為了測試是否已經(jīng)安裝成功,我們在運(yùn)行中輸入cmd
醒叁,打開命令提示符司浪,然后輸入node
,將會(huì)進(jìn)入Node.js的交互模式把沼。
通過這種方式安裝的 Node.js 還自動(dòng)附帶了npm啊易,我們可以在命令提示符中直接輸入npm
來使用它。
Node包管理器(npm)是一個(gè)由Node.js官方提供的第三方包管理工具饮睬,通過Node.js執(zhí)行租谈,能解決Node.js代碼部署上的很多問題,常見的使用場景有以下幾種:
- 允許用戶從NPM服務(wù)器下載別人編寫的第三方包到本地使用续捂。
- 允許用戶從NPM服務(wù)器下載并安裝別人編寫的命令行程序到本地使用垦垂。
- 允許用戶將自己編寫的包或命令行程序上傳到NPM服務(wù)器供別人使用。
可以通過輸入npm -v
來測試是否成功安裝牙瓢。
建立HTTP服務(wù)器
Node.js是為網(wǎng)絡(luò)而誕生的平臺(tái)劫拗,不同于“瀏覽器-HTTP 服務(wù)器-PHP 解釋器”的組織方式,Node.js將“HTTP服務(wù)器”這一層抽離矾克,直接面向?yàn)g覽器用戶页慷。
Chap4-2.js
var http=require('http'); //http模塊可以創(chuàng)建服務(wù)器應(yīng)用實(shí)例,也能發(fā)送http請求
http.createServer(function (req,res) {
res.writeHead(200,{"Content-Type":"text/html"});
res.write("<h1>Node.js</h1>");
res.end("<p style='font-size: x-large'>Hello World</p>");
}).listen(3000);
console.log("HTTP server is listening at port 3000.");
模塊與包
模塊(Module)和包(Package)是Node.js最重要的支柱胁附。開發(fā)一個(gè)具有一定規(guī)模的程序不可能只用一個(gè)文件酒繁,通常需要把各個(gè)功能拆分、封裝控妻,然后組合起來州袒,模塊正是為了實(shí)現(xiàn)這種方式而誕生的。
Node.js提供了require
函數(shù)來調(diào)用其他模塊弓候,而且模塊都是基于文件的郎哭,機(jī)制十分簡單。
我們經(jīng)常把 Node.js 的模塊和包相提并論菇存,因?yàn)槟K和包是沒有本質(zhì)區(qū)別的夸研,兩個(gè)概念也時(shí)常混用依鸥。如果要辨析亥至,那么可以把包理解成是實(shí)現(xiàn)了某個(gè)功能模塊的集合,用于發(fā)布和維護(hù)贱迟。
創(chuàng)建模塊
在 Node.js中姐扮,創(chuàng)建一個(gè)模塊非常簡單,因?yàn)橐粋€(gè)文件就是一個(gè)模塊关筒,我們要關(guān)注的問題僅僅在于如何在其他文件中獲取這個(gè)模塊溶握。
Node.js 提供了exports
和require
兩個(gè)對象,其中exports
是模塊公開的接口蒸播,require
用于從外部獲取一個(gè)模塊的接口睡榆,即所獲取模塊的exports
對象。
module.js
通過exports
對象把setName
和sayHello
作為模塊的訪問接口袍榆。
var name;
exports.setName=function (theName) {
name=theName;
};
exports.sayHello=function () {
return "hello "+name;
};
Chap4-3.js
在chap4-3.js中通過require('./module')
加載這個(gè)模塊胀屿,然后就可以直接訪問module.js中exports
對象的成員函數(shù)了。
var http=require('http'); //http模塊可以創(chuàng)建服務(wù)器應(yīng)用實(shí)例包雀,也能發(fā)送http請求
var mymodule=require("./module");
mymodule.setName("Zhang San");
http.createServer(function (req,res) {
res.writeHead(200,{"Content-Type":"text/html"});
res.write("<h1>Node.js</h1>");
res.end("<p style='font-size: x-large'>"+mymodule.sayHello()+"</p>");
}).listen(3000);
console.log("HTTP server is listening at port 3000.");
npm提供的上萬個(gè)模塊都是通過這種簡單的方式搭建起來的宿崭。
創(chuàng)建包
包是在模塊基礎(chǔ)上更深一步的抽象,它將某個(gè)獨(dú)立的功能封裝起來才写,用于發(fā)布葡兑、更新奖蔓、依賴管理和版本控制。Node.js根據(jù)CommonJS規(guī)范實(shí)現(xiàn)了包機(jī)制讹堤,開發(fā)了npm來解決包的發(fā)布和獲取需求吆鹤。
Node.js的包是一個(gè)目錄,其中包含一個(gè) JSON 格式的包說明文件package.json洲守。嚴(yán)格符合 CommonJS規(guī)范的包應(yīng)該具備以下特征:
- package.json必須在包的頂層目錄下疑务;
- 二進(jìn)制文件應(yīng)該在bin目錄下;
- JavaScript代碼應(yīng)該在lib目錄下梗醇;
- 文檔應(yīng)該在doc目錄下知允;
- 單元測試應(yīng)該在test目錄下。
Node.js對包的要求并沒有這么嚴(yán)格叙谨,只要頂層目錄下有package.json温鸽,并符合一些規(guī)范即可。
作為文件夾的模塊
模塊與文件是一一對應(yīng)的手负。文件不僅可以是 JavaScript 代碼或二進(jìn)制代碼嗤朴,還可以是一個(gè)文件夾。最簡單的包虫溜,就是一個(gè)作為文件夾的模塊雹姊。
例如:建立一個(gè)叫做somepackage的文件夾,在其中創(chuàng)建index.js:
exports.hello=function () {console.log("hello.");};
然后在somepackage之外建立Chap4-4.js:
Chap4-4.js
var somePackage=require("./somepackage");
somePackage.hello();
我們使用這種方法可以把文件夾封裝為一個(gè)模塊衡楞,即所謂的包吱雏。包通常是一些模塊的集合,在模塊的基礎(chǔ)上提供了更高層的抽象瘾境,相當(dāng)于提供了一些固定接口的函數(shù)庫歧杏。
package.json
通過定制package.json,我們可以創(chuàng)建更復(fù)雜迷守、更完善犬绒、更符合規(guī)范的包用于發(fā)布。在前面例子中的somepackage文件夾下兑凿,我們創(chuàng)建一個(gè)叫做package.json的文件凯力,內(nèi)容如下所示:
{"main":"./lib/interface.js"}
然后將index.js重命名為interface.js并放入lib子文件夾下。以同樣的方式再次調(diào)用這個(gè)包礼华,依然可以正常使用咐鹤。
Node.js在調(diào)用某個(gè)包時(shí),會(huì)首先檢查包中package.json文件的main字段圣絮,將其作為包的接口模塊祈惶,如果package.json或main字段不存在,會(huì)嘗試尋找index.js或index.node作為包的接口。
package.json是CommonJS規(guī)定的用來描述包的文件捧请,完全符合規(guī)范的package.json文件應(yīng)該含有以下字段:
-
name
:包的名稱凡涩,必須是唯一的,由小寫英文字母疹蛉、數(shù)字和下劃線組成突照,不能包含空格。 -
description
:包的簡要說明氧吐。 -
version
:符合語義化版本識(shí)別規(guī)范的版本字符串。 -
keywords
:關(guān)鍵字?jǐn)?shù)組末盔,通常用于搜索筑舅。 -
maintainers
:維護(hù)者數(shù)組,每個(gè)元素要包含name
陨舱、email
(可選)翠拣、web
(可選)字段。 -
contributors
:貢獻(xiàn)者數(shù)組游盲,格式與maintainers
相同误墓。包的作者應(yīng)該是貢獻(xiàn)者數(shù)組的第一個(gè)元素。 -
bugs
:提交bug的地址益缎,可以是網(wǎng)址或者電子郵件地址谜慌。 -
licenses
:許可證數(shù)組,每個(gè)元素要包含type
(許可證的名稱)和url
(鏈接到許可證文本的地址)字段莺奔。 -
main
:入口文件欣范,如果不存在這個(gè)字段,會(huì)自動(dòng)按下面順序查找:index.js
令哟、index.node
恼琼、index.json
。 -
dependencies
:當(dāng)前包所需的依賴包屏富,一個(gè)關(guān)聯(lián)數(shù)組晴竞,由包名稱和版本號(hào)組成政基。 -
repositories
:源代碼的托管倉庫位置鞠苟,每個(gè)元素要包含type
(倉庫的類型,如git
)爽室、url
(倉庫的地址)和path
(相對于倉庫的路徑神年,可選)字段甜滨。
Node.js包管理器
npm是 Node.js 官方提供的包管理工具,它已經(jīng)成了 Node.js 包的標(biāo)準(zhǔn)發(fā)布平臺(tái)瘤袖,用于 Node.js 包的發(fā)布衣摩、傳播、依賴控制。npm 提供了命令行工具艾扮,使你可以方便地下載既琴、安裝、升級(jí)泡嘴、刪除包甫恩,也可以讓你作為開發(fā)者發(fā)布并維護(hù)包。
獲取一個(gè)包
使用 npm 安裝包的命令格式為:npm [install/i] [package_name]
npm在默認(rèn)情況下會(huì)從http://npmjs.org搜索或下載包酌予,將包安裝到當(dāng)前目錄的node_modules子目錄下磺箕。
本地模式和全局模式
在使用npm安裝包的時(shí)候,有兩種模式:本地模式和全局模式抛虫。默認(rèn)情況下我們使用npm install
命令就是采用本地模式松靡,即把包安裝到當(dāng)前目錄的node_modules子目錄下。Node.js的require
在加載模塊時(shí)會(huì)嘗試搜尋node_modules子目錄建椰,因此使用 npm 本地模式安裝的包可以直接被引用雕欺。
npm 還有另一種不同的安裝模式被成為全局模式,使用方法為:npm [install/i] -g [package_name]
當(dāng)使用全局模式安裝時(shí)棉姐,npm會(huì)將包安裝到系統(tǒng)目錄屠列,譬如:C:\Users\admin\node_modules。
注意:使用全局模式安裝的包并不能直接在JavaScript文件中用require
獲得伞矩,因?yàn)?code>require不會(huì)搜索 /User/admin/node_modules笛洛。
總而言之,當(dāng)我們要把某個(gè)包作為工程運(yùn)行時(shí)的一部分時(shí)乃坤,通過本地模式獲取撞蜂,如果要在命令行下使用,則使用全局模式安裝侥袜。
Node核心模塊
- 全局對象
- 常用工具
- 事件機(jī)制
- 文件系統(tǒng)訪問
- URL &querystring模塊
- HTTP服務(wù)器與客戶端
全局對象
Node.js 中的全局對象是global蝌诡,所有全局變量(除了global本身以外)都是global對象的屬性,例如console
枫吧、exports
浦旱、process
等。
process
對象
process
對象是一個(gè)全局變量九杂,它提供當(dāng)前Node.js進(jìn)程的有關(guān)信息颁湖,以及控制當(dāng)前Node.js進(jìn)程。 因?yàn)槭侨肿兞坷。詿o需使用require()
甥捺。
-
process.argv
屬性返回一個(gè)數(shù)組,這個(gè)數(shù)組包含了啟動(dòng)Node.js進(jìn)程時(shí)的命令行參數(shù)镀层。第一個(gè)元素為node
镰禾,第二個(gè)元素為當(dāng)前執(zhí)行的JavaScript文件路徑。剩余的元素為其他命令行參數(shù)。Chap4-5.js
process.argv.forEach(function(val,index){ console.log(index+":"+val); });
運(yùn)行以下命令吴侦,啟動(dòng)進(jìn)程:
node chap4-5.js one two=three four
process.stdout
是標(biāo)準(zhǔn)輸出流屋休,通常我們使用的console.log()
向標(biāo)準(zhǔn)輸出打印字符,而process.stdout.write()
函數(shù)提供了更底層的接口备韧。-
process.stdin
是標(biāo)準(zhǔn)輸入流劫樟。Chap4-5.js
var num1, num2; process.stdout.write('請輸入num1的值:');//向屏幕輸出,提示信息织堂,要求輸入num1 /*監(jiān)聽用戶的輸入*/ process.stdin.on('data', function (chunk) { if (!num1) { num1 = Number(chunk); process.stdout.write('請輸入num2的值');//向屏幕輸出叠艳,提示信息,要求輸入num2 } else { num2 = Number(chunk); process.stdout.write('結(jié)果是:' + (num1 + num2)); } });
console
對象
用于向標(biāo)準(zhǔn)輸出流(stdout)或標(biāo)準(zhǔn)錯(cuò)誤流(stderr)輸出字符易阳。
-
console.log()
:向標(biāo)準(zhǔn)輸出流打印字符并以換行符結(jié)束附较,其可以接受若干個(gè)參數(shù)。const count = 5; console.log('count: %d', count);
-
console.error()
:與console.log()
用法相同闽烙,只是向標(biāo)準(zhǔn)錯(cuò)誤流輸出。console.error('error #%d', count);
__dirname
屬性
返回當(dāng)前模塊的文件夾名稱声搁。等同于__filename
的path.dirname()
的值黑竞。
console.log(__dirname); //返回D:\教學(xué)\講義\網(wǎng)絡(luò)技術(shù)與應(yīng)用\programming\myNode\chap4
__filename
屬性
返回當(dāng)前模塊的文件名稱。
console.log(__filename); //返回D:\教學(xué)\講義\網(wǎng)絡(luò)技術(shù)與應(yīng)用\programming\myNode\chap4\chap4-6.js
require()
方法
引入模塊:
-
引入同目錄下的包(根據(jù)文件夾名稱)
注意:包名稱前面需要加
./
Chap4-3.js
var http=require('http'); //http模塊可以創(chuàng)建服務(wù)器應(yīng)用實(shí)例疏旨,也能發(fā)送http請求 var mymodule=require("./module"); mymodule.setName("Zhang San"); http.createServer(function (req,res) { res.writeHead(200,{"Content-Type":"text/html"}); res.write("<h1>Node.js</h1>"); res.end("<p style='font-size: x-large'>"+mymodule.sayHello()+"</p>"); }).listen(3000); console.log("HTTP server is listening at port 3000.");
-
引入同目錄下node_modules目錄下的包
包的路徑:
\myNode\node\_modules\somepackage\index.js
Chap4-7.js的路徑:
\myNode\chap4-7.js
Chap4-7.js
var somePackage=require("somepackage"); somePackage.hello();
常用工具util
util
模塊很魂,提供常用函數(shù)的集合,用于彌補(bǔ)核心JavaScript的功能過于精簡的不足檐涝。 它可以通過以下方式使用:var util = require('util');
util.inherits(constructor, superConstructor)
從一個(gè)構(gòu)造函數(shù)中繼承原型方法到另一個(gè)遏匆。constructor
的原型會(huì)被設(shè)置到一個(gè)從superConstructor
創(chuàng)建的新對象上。
Chap4-8.js
var util=require("util");
function Base() {
this.name="base";
this.base=1991;
this.sayHello=function () {
console.log("hello "+this.name);
};
}
Base.prototype.showName=function () {
console.log(this.name);
};
function Sub() {
this.name="sub";
}
util.inherits(Sub,Base);
var objBase=new Base();
objBase.showName();
objBase.sayHello();
console.log(objBase);
var objSub=new Sub();
objSub.showName();
console.log(objSub);
輸出結(jié)果:
base
hello base
Base { name: 'base', base: 1991, sayHello: [Function] }
sub
Sub { name: 'sub' }
util.inspect(object[, options])
返回object
的字符串表示谁榜,主要用于調(diào)試幅聘。
options
可用于改變格式化字符串的某些方面:
-
showHidden
,如果為true
窃植,則object
的不可枚舉的符號(hào)與屬性也會(huì)被包括在格式化后的結(jié)果中帝蒿。默認(rèn)為false
。 -
depth
表示最大遞歸的層數(shù)巷怜,如果對象很復(fù)雜葛超,你可以指定層數(shù)以控制輸出信息的多少。如果不指定depth
延塑,默認(rèn)會(huì)遞歸2層绣张,指定為null
表示將不限遞歸層數(shù)完整遍歷對象。 -
color
值為true
关带,輸出格式將會(huì)以ANSI
顏色編碼侥涵,通常用于在終端顯示更漂亮的效果。
Chap4-9.js
var util=require("util");
function Person() {
this.name="byvoid";
this.toString=function () {
return this.name;
};
}
var obj=new Person();
console.log(util.inspect(obj));
console.log(util.inspect(obj,true));
輸出結(jié)果:
Person { name: 'byvoid', toString: [Function] }
Person {
name: 'byvoid',
toString:
{ [Function]
[length]: 0,
[name]: '',
[arguments]: null,
[caller]: null,
[prototype]: { [constructor]: [Circular] } } }
事件機(jī)制
events
是Node.js最重要的模塊,沒有“之一”独令,原因是Node.js本身架構(gòu)就是事件式的端朵,而它提供了唯一的接口,所以堪稱Node.js事件編程的基石燃箭。events
模塊不僅用于用戶代碼與Node.js下層事件循環(huán)的交互冲呢,還幾乎被所有的模塊依賴。
events
模塊只提供了一個(gè)對象: events.EventEmitter
招狸。EventEmitter
的核心就是事件發(fā)射與事件監(jiān)聽器功能的封裝敬拓。
EventEmitter
的每個(gè)事件由一個(gè)事件名和若干個(gè)參數(shù)組成,事件名是一個(gè)字符串裙戏,通常表達(dá)一定的語義乘凸。對于每個(gè)事件,EventEmitter
支持若干個(gè)事件監(jiān)聽器累榜。當(dāng)事件發(fā)射時(shí)营勤,注冊到這個(gè)事件的事件監(jiān)聽器被依次調(diào)用,事件參數(shù)作為回調(diào)函數(shù)參數(shù)傳遞壹罚。
Chap4-10.js
var events=require("events");
var emitter=new events.EventEmitter();
emitter.on("someEvent",function (arg1,arg2) {
console.log("Listener1",arg1,arg2);
});
emitter.on("someEvent",function (arg1,arg2) {
console.log("Listener2",arg1,arg2);
});
emitter.emit("someEvent","byvoid",1991);
輸出結(jié)果:
Listener1 byvoid 1991
Listener2 byvoid 1991
EventEmitter 對象的方法 |
說明 |
---|---|
addListener(event, listener) |
為指定事件添加一個(gè)監(jiān)聽器到監(jiān)聽器數(shù)組的尾部 |
on(event, listener) |
為指定事件注冊一個(gè)監(jiān)聽器葛作,接受一個(gè)字符串event 和一個(gè)回調(diào)函數(shù) |
once(event, listener) |
為指定事件注冊一個(gè)單次監(jiān)聽器,即 監(jiān)聽器最多只會(huì)觸發(fā)一次猖凛,觸發(fā)后立刻解除該監(jiān)聽器 |
removeListener(event, listener) |
移除指定事件的某個(gè)監(jiān)聽器赂蠢,監(jiān)聽器必須是該事件已經(jīng)注冊過的監(jiān)聽器。它接受兩個(gè)參數(shù)辨泳,第一個(gè)是事件名稱虱岂,第二個(gè)是回調(diào)函數(shù)名稱 |
removeAllListeners([event]) |
移除所有事件的所有監(jiān)聽器, 如果指定事件菠红,則移除指定事件的所有監(jiān)聽器 |
setMaxListeners(n) |
默認(rèn)情況下第岖, EventEmitters 如果你添加的監(jiān)聽器超過 10 個(gè)就會(huì)輸出警告信息。setMaxListeners 函數(shù)用于提高監(jiān)聽器的默認(rèn)限制的數(shù)量 |
listeners(event) |
返回指定事件的監(jiān)聽器數(shù)組 |
emit(event, [arg1], [arg2], [...]) |
按參數(shù)的順序執(zhí)行每個(gè)監(jiān)聽器试溯,如果事件有注冊監(jiān)聽返回true 绍傲,否則返回false
|
EventEmitter 類方法 |
說明 |
---|---|
listenerCount(emitter, event) |
返回指定事件的監(jiān)聽器數(shù)量。 |
Chap4-10.js
var events = require('events');
var eventEmitter = new events.EventEmitter();
var listener1 = function listener1() {console.log('監(jiān)聽器 listener1 執(zhí)行耍共。');} // 監(jiān)聽器 #1
var listener2 = function listener2() {console.log('監(jiān)聽器 listener2 執(zhí)行烫饼。');} // 監(jiān)聽器 #2
var listener3 = function listener3() {console.log('監(jiān)聽器 listener3 執(zhí)行。');} // 監(jiān)聽器 #3
// 綁定 connection 事件试读,處理函數(shù)為 listener1
eventEmitter.addListener('connection', listener1 );
// 綁定 connection 事件杠纵,處理函數(shù)為 listener2
eventEmitter.on('connection', listener2 );
// 綁定 connection 事件,處理函數(shù)為 listener3
eventEmitter.once('connection', listener3 );
var eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection');
console.log(eventListeners + " 個(gè)監(jiān)聽器監(jiān)聽連接事件钩骇。");
// 處理 connection 事件
eventEmitter.emit('connection');
// 移除監(jiān)綁定的 listener1 函數(shù)
eventEmitter.removeListener('connection', listener1 );
console.log("listener1 不再受監(jiān)聽比藻。");
// 觸發(fā)連接事件
eventEmitter.emit('connection');
eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection');
console.log(eventListeners + " 個(gè)監(jiān)聽器監(jiān)聽連接事件铝量。");
console.log("程序執(zhí)行完畢。");
文件系統(tǒng)訪問
fs
模塊是文件操作的封裝银亲,它提供了文件的讀取慢叨、寫入、更名务蝠、刪除碉京、遍歷目錄秧廉、鏈接等文件系統(tǒng)操作荠雕。
Node導(dǎo)入文件系統(tǒng)模塊(fs
)語法如下所示:var fs = require("fs")
fs.readFile(filename[, encoding][, callback(err,data)])
filename
湃望,表示要讀取的文件名;
encoding
院喜,是可選的亡蓉,表示文件的字符編碼;
callback
喷舀,是回調(diào)函數(shù)砍濒,用于接收文件的內(nèi)容×蚵椋回調(diào)函數(shù)提供兩個(gè)參數(shù)err
和data
爸邢,err
表示有沒有錯(cuò)誤發(fā)生,data
是文件內(nèi)容庶香。如果指定了encoding
甲棍,data
是一個(gè)解析后的字符串简识,否則data
將會(huì)是以Buffer形式表示的二進(jìn)制數(shù)據(jù)赶掖。
Chap4-11.js
var fs=require('fs'); //內(nèi)置文件系統(tǒng)模塊fs
fs.readFile('files/content.txt','utf-8',function (err,data) {
if(err){
console.error(err);
}else {
console.log("utf-8");
console.log(data);
}
});
fs.readFile('files/content.txt',function (err,data) {
if(err){
console.error(err);
}else {
console.log("缺省encoding");
console.log(data);
}
});
輸出結(jié)果:
utf-8
Text 文本文件實(shí)例
缺省encoding
<Buffer 54 65 78 74 20 e6 96 87 e6 9c ac e6 96 87 e4 bb b6 e5 ae 9e e4 be 8b>
fs.readFileSync(filename, [encoding])
是fs.readFile
同步的版本。
它接受的參數(shù)和fs.readFile
相同七扰,而讀取到的文件內(nèi)容會(huì)以函數(shù)返回值的形式返回奢赂。如果有錯(cuò)誤發(fā)生,fs
將會(huì)拋出異常颈走,你需要使用try
和catch
捕捉并處理異常膳灶。
Chap4-1-2.js
var fs=require('fs'); //內(nèi)置文件系統(tǒng)模塊fs
console.log("同步讀取文件");
var data=fs.readFileSync('chap3.js','utf-8');
console.log(data);
console.log("end");
fs.open(path, flags, [mode], [callback(err, fd)])
異步地打開文件。
path
為文件的路徑立由;
flags
可以是以下值:
-
r
:以讀取模式打開文件轧钓。 -
r+
:以讀寫模式打開文件。 -
w
:以寫入模式打開文件锐膜,如果文件不存在則創(chuàng)建毕箍。 -
w+
:以讀寫模式打開文件,如果文件不存在則創(chuàng)建道盏。 -
a
:以追加模式打開文件而柑,如果文件不存在則創(chuàng)建文捶。 -
a+
:以讀取追加模式打開文件,如果文件不存在則創(chuàng)建媒咳。
mode
參數(shù)用于創(chuàng)建文件時(shí)給文件指定權(quán)限粹排。但只有當(dāng)文件被創(chuàng)建時(shí)才有效。默認(rèn)為0666
涩澡,可讀寫顽耳。
fd
為一個(gè)整數(shù),表示打開文件返回的文件描述符筏养。
fs.read(fd, buffer, offset, length, position, [callback(err, bytesRead, buffer)])
功能是從指定的文件描述符fd
中讀取數(shù)據(jù)并寫入buffer
指向的緩沖區(qū)對象斧抱。
offset
是buffer
的寫入偏移量;
length
是要從文件中讀取的字節(jié)數(shù)渐溶;
position
是文件讀取的起始位置辉浦,如果position
的值為null
,則會(huì)從當(dāng)前文件指針的位置讀染シ宪郊;
回調(diào)函數(shù)傳遞bytesRead
和`buffer,分別表示讀取的字節(jié)數(shù)和緩沖區(qū)對象拖陆。
fs.close(fd, [callback(err)])
為異步模式下關(guān)閉文件弛槐。
Chap4-12.js
一般來說,除非必要依啰,否則不要使用這種方式讀取文件乎串,因?yàn)樗竽闶謩?dòng)管理緩沖區(qū)和文件指針,尤其是在你不知道文件大小的時(shí)候速警,這將會(huì)是一件很麻煩的事情叹誉。
var fs=require("fs");
fs.open("files/content.txt","r",function (err,fd) {
if(err){
console.error(err);
return;
}
var buf=new Buffer(8);
fs.read(fd,buf,0,8,null,function (err,bytesRead,buffer) {
if(err){
console.error(err);
return;
}
console.log("bytesRead:"+bytesRead);
console.log(buffer);
})
fs.close(fd,function (err) {
if(err){
return console.error(err);
}
});
});
輸出結(jié)果:
bytesRead:8
<Buffer 54 65 78 74 20 e6 96 87>
fs.writeFile(file, data[, encoding][, callback(err)])
功能是異步地寫入數(shù)據(jù)到文件,如果文件已經(jīng)存在闷旧,則替代文件长豁;
file
,文件名或文件描述符忙灼;
data
可以是一個(gè)字符串或一個(gè)buffer
匠襟。
Chap4-13.js
var fs=require("fs");
console.log("準(zhǔn)備寫入文件");
fs.writeFile("files/input.txt","我是通過fs.writeFile寫入文件的內(nèi)容","utf8",function (err) {
if(err){
return console.error(err);
}
console.log("數(shù)據(jù)寫入成功!");
})
fs.write(fd,buffer,offset,length,position,[callback(err, bytesWritten, buffer)])
功能是寫入buffer
到fd
指定的文件该园;
offset
是buffer
中被寫入偏移量酸舍;
length
指定要寫入的字節(jié)數(shù);
position
指向從文件開始寫入數(shù)據(jù)的位置里初,如果position
的值為null
啃勉,則會(huì)從當(dāng)前文件指針的位置寫入;
回調(diào)函數(shù)傳遞bytesWritten
和buffer
青瀑,分別表示寫入的字節(jié)數(shù)和緩沖區(qū)對象璧亮。
在Node.js中萧诫,定義了一個(gè)Buffer類,該類用來創(chuàng)建一個(gè)專門存放二進(jìn)制數(shù)據(jù)的緩存區(qū)枝嘶。
Chap4-14.js
var fs=require("fs");
fs.open("files/index2.txt","w",function (err,fd) {
if(err){
return console.error(err);
}
var buffer=new Buffer("Hello World!");
fs.write(fd,buffer,0,12,null,function (err,bytesWritten,buffer) {
if(err){
return console.error(err);
}
console.log(bytesWritten,buffer.slice(0,bytesWritten).toString());
fs.close(fd);
})
});
url
& querystring
模塊
url
模塊
url
模塊提供了一些實(shí)用函數(shù)帘饶,用于 url處理與解析,url
字符串是一個(gè)結(jié)構(gòu)化的字符串群扶,包含多個(gè)有意義的組成部分及刻,被解析時(shí),會(huì)返回一個(gè)URL對象竞阐,包含每個(gè)組成部分的屬性缴饭。
url
模塊的方法有三個(gè):
url.parse(urlStr[, parseQueryString][, slashesDenoteHost])
將url字符串轉(zhuǎn)換成object
對象
urlStr
:需要處理的url字符串;
parseQueryString
:是否將查詢參數(shù)也解析成對象骆莹。為true
時(shí)將使用查詢模塊分析查詢字符串颗搂,默認(rèn)為false
;
slashesDenoteHost
:解析主機(jī)處理幕垦,雙斜線表示主機(jī)丢氢。
- 默認(rèn)為
false
,//foo/bar
形式的字符串將被解釋成{ pathname: '//foo/bar' }
先改。 - 如果設(shè)置成
true
疚察,//foo/bar
形式的字符串將被解釋成{ host: 'foo', pathname: '/bar' }
var url=require('url');
var url1='http://calc.gongjuji.net/byte/?name=zhangsan&age=18#one#two';
console.log(url.parse(url1));
// { protocol: 'http:', //使用協(xié)議
// slashes: null, //
// auth: null, // 驗(yàn)證信息
// host: 'calc.gongjuji.net', //全小寫的主機(jī)部分的URL,包括端口信息仇奶。
// port: null, //端口
// hostname: 'calc.gongjuji.net',//小寫的主機(jī)部分的主機(jī)
// hash: '#one#two', //頁面錨點(diǎn)參數(shù)部分
// search: '?name=zhangsan&age=18',//查詢參數(shù)部分貌嫡,帶?
// query: 'name=zhangsan&age=18', //查詢參數(shù)部分
// pathname: '/byte/', //目錄部分
// path: '/byte/?name=zhangsan&age=18',//目錄+參數(shù)部分
// href: 'http://calc.gongjuji.net/byte/?name=zhangsan&age=18#one#two' //最初解析的完整的網(wǎng)址该溯。雙方的協(xié)議和主機(jī)是小寫岛抄。
// }
var url2='//www.gongjuji.net/byte/?name=zhangsan#one';
console.log(url.parse(url2,true,true));
// { protocol: null,
// slashes: true,
// auth: null,
// host: 'www.gongjuji.net',
// port: null,
// hostname: 'www.gongjuji.net',
// hash: '#one',
// search: '?name=zhangsan',
// query: { name: 'zhangsan' },
// pathname: '/byte/',
// path: '/byte/?name=zhangsan',
// href: '//www.gongjuji.net/byte/?name=zhangsan#one' }
var url=require('url');
var url2='//www.gongjuji.net/byte/?name=zhangsan#one';
console.log(url.parse(url2,true));
// { protocol: null,
// slashes: null,
// auth: null,
// host: null,
// port: null,
// hostname: null,
// hash: '#one',
// search: '?name=zhangsan',
// query: { name: 'zhangsan' },
// pathname: '//www.gongjuji.net/byte/',
// path: '//www.gongjuji.net/byte/?name=zhangsan',
// href: '//www.gongjuji.net/byte/?name=zhangsan#one' }
url.format(urlObj)
將json對象格式化成字符串。
var url=require('url');
var obj1={ protocol: 'http:',
slashes: true,
auth: null,
host: 'calc.gongjuji.net',
port: null,
hostname: 'calc.gongjuji.net',
hash: '#one#two',
search: '?name=zhangsan&age=18',
query: 'name=zhangsan&age=18',
pathname: '/byte/',
path: '/byte/?name=zhangsan&age=18',
href: 'http://calc.gongjuji.net/byte/?name=zhangsan&age=18#one#two'
};
var url1=url.format(obj1);
console.log(url1);
//http://calc.gongjuji.net/byte/?name=zhangsan&age=18#one#two
var url=require('url');
//請求參數(shù)為為json對象
var obj2={ protocol: 'http:',
slashes: true,
auth: null,
host: 'calc.gongjuji.net',
port: null,
hostname: 'calc.gongjuji.net',
hash: '#one#two',
search: '?name=zhangsan&age=18',
query: { name: 'zhangsan', age: '18' }, //頁面參數(shù)部分朗伶,已經(jīng)解析成對象了
pathname: '/byte/',
path: '/byte/?name=zhangsan&age=18',
href: 'http://calc.gongjuji.net/byte/?name=zhangsan&age=18#one#two' };
var url2=url.format(obj2);
console.log(url2);
//http://calc.gongjuji.net/byte/?name=zhangsan&age=18#one#two
var url=require('url');
//缺少參數(shù)的情況
var obj3={ protocol: null,
slashes: true,
auth: null,
host: 'www.gongjuji.net',
port: null,
hostname: 'www.gongjuji.net',
hash: '#one',
search: '?name=zhangsan',
query: { name: 'zhangsan' },
pathname: '/byte/',
path: '/byte/?name=zhangsan',
href: '//www.gongjuji.net/byte/?name=zhangsan#one' };
var url3=url.format(obj3);
console.log(url3);
//www.gongjuji.net/byte/?name=zhangsan#one
url.resolve(from, to)
為URL或href
插入或替換原有的標(biāo)簽弦撩。
from
:源地址步咪;
to
:需要添加或替換的標(biāo)簽论皆。
var url=require('url');
//指定相對路徑
var url1=url.resolve('http://www.gongjuji.net/one/two/three','four');
console.log(url1); //http://www.gongjuji.net/one/two/four
//指定根目錄的相對路徑
var url3=url.resolve('http://www.gongjuji.net/one/two/three','/four');
console.log(url3); //http://www.gongjuji.net/four
//帶參數(shù)的相對路徑
var url2=url.resolve('http://www.gongjuji.net/one/two/three?name=zhangsan','four');
console.log(url2); //http://www.gongjuji.net/one/two/four
//非標(biāo)準(zhǔn)分隔符的原路徑
var url4=url.resolve('http://www.gongjuji.net\\one#name1','/four');
console.log(url4);//http://www.gongjuji.net/four
//非標(biāo)準(zhǔn)分隔符的相對路徑
var url5=url.resolve('http://www.gongjuji.net/one','\\two\\three');
console.log(url5);//http://www.gongjuji.net/two/three
querystring
模塊
querystring
模塊提供了一些實(shí)用函數(shù),用于解析與格式化 URL 查詢字符串猾漫。
querystring
模塊的方法有四個(gè):
querystring 模塊方法 |
說明 |
---|---|
querystring.escape(str) |
將一個(gè)字符轉(zhuǎn)義成一個(gè)編碼 |
querystring.unescape(str) |
將一個(gè)編碼反轉(zhuǎn)義成一個(gè)字符 |
querystring.stringify(obj[, sep[, eq[, options]]]) |
將一個(gè)對象序列化為一個(gè)查詢的字符串点晴,中間使用& 和 = 分別為字符串中的分隔符和賦值符。其中悯周,obj :要序列化成 URL 查詢字符串的對象粒督。sep :用于界定查詢字符串中的鍵值對的子字符串,默認(rèn)為& 禽翼。eq :用于界定查詢字符串中的鍵與值的子字符串屠橄,默認(rèn)為= 族跛。options :encodeURIComponent <Function> 把對象中的字符轉(zhuǎn)換成查詢字符串時(shí)使用的函數(shù),默認(rèn)為querystring.escape() 锐墙。 |
querystring.parse(str[, sep[, eq[, options]]]) |
將一個(gè)查詢的字符串反序列化為一個(gè)對象礁哄,也就是說它與querystring.stringify 是起相反作用的關(guān)系 |
Chap4-17.js
var queryString=require("querystring");
var str=queryString.escape("哈哈");
console.log(str); //%E5%93%88%E5%93%88
console.log(queryString.unescape(str)); //哈哈
console.log(queryString.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' }));
// 返回 'foo=bar&baz=qux&baz=quux&corge='
console.log(queryString.stringify({ foo: 'bar', baz: 'qux' }, ';', ':'));
// 返回 'foo:bar;baz:qux'
console.log(queryString.parse('name=pkcms&author=zh&date='));
//{ name: 'pkcms', author: 'zh', date: '' }
console.log(queryString.parse('name=pkcms&author=zh&author=hhy&date='));
//相同的參數(shù)名會(huì)反序列化為一個(gè)數(shù)組,{ name: 'pkcms', author: [ 'zh', 'hhy' ], date: '' }
console.log(queryString.parse('name=pkcms,author=zh,date=',','));
//第2個(gè)參數(shù)是用來指明分隔符是用了哪個(gè)字符,{ name: 'pkcms', author: 'zh', date: '' }
console.log(queryString.parse('name:pkcms,author:zh,date:',',',':'));
//第3個(gè)參數(shù)是用來指明賦值符是用了哪個(gè)字符,{ name: 'pkcms', author: 'zh', date: '' }
HTTP服務(wù)器與客戶端
Node.js 標(biāo)準(zhǔn)庫提供了http
模塊,其中封裝了一個(gè)高效的HTTP服務(wù)器和一個(gè)簡易的HTTP客戶端溪北。http.Server
是一個(gè)基于事件的HTTP服務(wù)器桐绒,http.request
則是一個(gè)HTTP客戶端工具,用于向HTTP服務(wù)器發(fā)起請求之拨。
HTTP服務(wù)器
http.Server
是http
模塊中的HTTP服務(wù)器對象茉继,用Node.js做的所有基于HTTP
協(xié)議的系統(tǒng),如網(wǎng)站蚀乔、社交應(yīng)用甚至代理服務(wù)器烁竭,都是基于http.Server
實(shí)現(xiàn)的。
http.Server
是一個(gè)基于事件的HTTP服務(wù)器吉挣,所有的請求都被封裝為獨(dú)立的事件,開發(fā)者只需要對它的事件編寫響應(yīng)函數(shù)即可實(shí)現(xiàn)HTTP服務(wù)器的所有功能听想。它繼承自EventEmitter
腥刹,提供了以下幾個(gè)事件:
request
:當(dāng)客戶端請求到來時(shí),該事件被觸發(fā)汉买,提供兩個(gè)參數(shù)req
和res
衔峰,分別是http.ServerRequest
和http.ServerResponse
的實(shí)例,表示請求和響應(yīng)信息蛙粘。connection
:當(dāng)TCP連接建立時(shí)淀散,該事件被觸發(fā)撩轰,提供一個(gè)參數(shù)socket,為net.Socket
的實(shí)例。connection
事件的粒度要大于request
缩挑,因?yàn)榭蛻舳嗽?code>Keep-Alive模式下可能會(huì)在同一個(gè)連接內(nèi)發(fā)送多次請求。close
:當(dāng)服務(wù)器關(guān)閉時(shí)湃交,該事件被觸發(fā)镀首。注意不是在用戶連接斷開時(shí)。
在這些事件中伯复, 最常用的就是request
了慨代, 因此http
提供了一個(gè)捷徑:http.createServer([requestListener])
, 功能是創(chuàng)建一個(gè)HTTP服務(wù)器并將requestListener
作為 request 事件的監(jiān)聽函數(shù)啸如。
Chap4-2.js
var http=require('http')
http.createServer(function (req,res) {
res.writeHead(200,{"Content-Type":"text/html"});
res.write("<h1>Node.js</h1>");
res.end("<p style='font-size: x-large'>Hello World</p>");
}).listen(3000);
Chap4-15.js
var http=require("http");
var server=new http.Server();
var count=0;
server.on("connection",function () {
console.log("someone connected!")
});
server.on("request",function (req,res) {
res.writeHead(200,{"Content-Type":"text/html"});
res.write("<h1>Node.js</h1>");
res.end("<p style='font-size: x-large'>Hello World</p>");
});
server.on("close",function () {
console.log("server closed!")
});
server.listen(3000);
setTimeout(function () {
server.close();
},5000);
console.log("HTTP server is listening at port 3000.");
http.ServerRequest
http.ServerRequest
是HTTP請求的信息侍匙,是后端開發(fā)者最關(guān)注的內(nèi)容。它一般由http.Server
的request
事件發(fā)送叮雳,作為第一個(gè)參數(shù)傳遞想暗,通常簡稱request
或req
妇汗。
HTTP請求一般可以分為兩部分:請求頭(Request Header)和請求體(Requset Body)
ServerRequest 的屬性 |
說明 |
---|---|
complete |
客戶端請求是否已經(jīng)發(fā)送完成 |
httpVersion |
HTTP協(xié)議版本,通常是 1.0 或 1.1
|
method |
HTTP請求方法说莫,如 GET 铛纬、POST 、PUT 唬滑、DELETE 等 |
url |
原始的請求路徑告唆,例如/static/image/x.jpg 或 /user?name=byvoid
|
headers |
HTTP 請求頭 |
trailers |
HTTP 請求尾(不常見) |
connection |
當(dāng)前 HTTP 連接套接字,為 net.Socket 的實(shí)例 |
socket |
connection 屬性的別名 |
client |
client 屬性的別名 |
http.ServerRequest
提供了以下3個(gè)事件用于控制請求體傳輸:
-
data
:當(dāng)請求體數(shù)據(jù)到來時(shí)晶密,該事件被觸發(fā)擒悬。該事件提供一個(gè)參數(shù)chunk
,表示接收到的數(shù)據(jù)稻艰。如果該事件沒有被監(jiān)聽懂牧,那么請求體將會(huì)被拋棄。該事件可能會(huì)被調(diào)用多次尊勿。 -
end
:當(dāng)請求體數(shù)據(jù)傳輸完成時(shí)僧凤,該事件被觸發(fā),此后將不會(huì)再有數(shù)據(jù)到來元扔。 -
close
: 用戶當(dāng)前請求結(jié)束時(shí)躯保,該事件被觸發(fā)。不同于end
澎语,如果用戶強(qiáng)制終止了傳輸途事,也還是調(diào)用close
。
獲取 GET 請求內(nèi)容
由于 GET 請求直接被嵌入在路徑中擅羞,URL是完整的請求路徑尸变,包括了 ?
后面的部分,因此你可以手動(dòng)解析后面的內(nèi)容作為 GET請求的參數(shù)减俏。Node.js 的 url
模塊中的 parse
函數(shù)提供了這個(gè)功能召烂。
var http=require("http");
var url=require("url");
http.createServer(function (req,res) {
console.log(url.parse(req.url));
}).listen(3000);
http://localhost:3000/chap4-16?name=zhangsan&password=123456
Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?name=zhangsan&password=123456',
query: 'name=zhangsan&password=123456',
pathname: '/chap4-16',
path: '/chap4-16?name=zhangsan&password=123456',
href: '/chap4-16?name=zhangsan&password=123456' }
Chap4-16.html
<form action="http://localhost:3000/myNode/chap4/chap4-16.js" method="get">
<span>用戶名:</span><input type="text" name="user">
<span>密碼:</span><input type="password" name="password">
<input type="submit" value="提交">
</form>
Chap4-16.js
var http=require("http");
var url=require("url");
var queryString=require("querystring");
http.createServer(function (req,res) {
//可替換部分開始
var query=url.parse(req.url).query;
console.log(query);
var params=queryString.parse(query);
res.writeHead(200,{"Content-Type":"text/html;charset=utf-8"});
res.write("用戶名為:"+params.user);
res.end("密碼為:"+params.password);
//可替換部分結(jié)束
}).listen(3000);
console.log("HTTP server is listening at port 3000.");
可替換部分:
var query=url.parse(req.url,true).query;
res.writeHead(200,{"Content-Type":"text/html;charset=utf-8"});
res.write("用戶名為:"+query.user);
res.end("密碼為:"+query.password);
獲取 POST 請求內(nèi)容
POST 請求的內(nèi)容全部都在請求體中。
http.ServerRequest 并沒有一個(gè)屬性內(nèi)容為請求體娃承,原因是等待請求體傳輸可能是一件耗時(shí)的工作奏夫,譬如上傳文件。所以 Node.js 默認(rèn)是不會(huì)解析請求體的草慧,當(dāng)你需要的時(shí)候桶蛔,需要手動(dòng)來做匙头。
http.ServerResponse
http.ServerResponse
是返回給客戶端的信息漫谷,決定了用戶最終能看到的結(jié)果。作為第二個(gè)參數(shù)傳遞蹂析,一般簡稱為response
或 res
舔示。
http.ServerResponse
有三個(gè)重要的成員函數(shù)碟婆,用于返回響應(yīng)頭、響應(yīng)內(nèi)容以及結(jié)束請求惕稻。
response.writeHead(statusCode, [headers])
:向請求的客戶端發(fā)送響應(yīng)頭竖共。statusCode
是 HTTP 狀態(tài)碼,如200
(請求成功)俺祠、404
(未找到)等公给。headers
是一個(gè)類似關(guān)聯(lián)數(shù)組的對象,表示響應(yīng)頭的每個(gè)屬性蜘渣。該函數(shù)在一個(gè)請求內(nèi)最多只能調(diào)用一次淌铐,如果不調(diào)用,則會(huì)自動(dòng)生成一個(gè)響應(yīng)頭晚唇。response.write(data, [encoding])
:向請求的客戶端發(fā)送響應(yīng)內(nèi)容据某。data
是一個(gè)Buffer
或字符串沧奴,表示要發(fā)送的內(nèi)容。如果data
是字符串嚣潜,那么需要指定encoding
來說明它的編碼方式冬骚,默認(rèn)是utf-8
。在response.end
調(diào)用之前懂算,response.write
可以被多次調(diào)用只冻。response.end([data], [encoding])
:結(jié)束響應(yīng),告知客戶端所有發(fā)送已經(jīng)完成计技。當(dāng)所有要返回的內(nèi)容發(fā)送完畢的時(shí)候喜德,該函數(shù)必須被調(diào)用一次。它接受兩個(gè)可選參數(shù)垮媒,意義和response.write
相同舍悯。如果不調(diào)用該函數(shù),客戶端將永遠(yuǎn)處于等待狀態(tài)睡雇。
Chap4-18.html
<form action="http://localhost:3000/myNode/chap4/chap4-18.js" method=“post">
<span>用戶名:</span><input type="text" name="user">
<span>密碼:</span><input type="password" name="password">
<input type="submit" value="提交">
</form>
Chap4-18.js
var http=require("http");
var querystring=require("querystring");
var util=require("util");
http.createServer(function (req,res) {
var post="";
req.on("data",function (chunk) {
post+=chunk;
});
req.on("end",function () {
post=querystring.parse(post);
res.writeHead(200,{"Content-Type":"text/html;charset=utf-8"});
res.write("用戶名為:"+post.user);
res.end("密碼為:"+post.password);
});
}).listen(3000);
console.log("HTTP server is listening at port 3000.");
HTTP 客戶端
http
模塊提供了兩個(gè)函數(shù)http.request
和http.get
萌衬,功能是作為客戶端向 HTTP 服務(wù)器發(fā)起請求。
http.request(options, callback)
發(fā)起 HTTP 請求它抱,并返回一個(gè) http.ClientRequest
的實(shí)例奄薇。接受兩個(gè)參數(shù),option
是一個(gè)類似關(guān)聯(lián)數(shù)組的對象抗愁,表示請求的參數(shù)馁蒂,callback
是請求的回調(diào)函數(shù)。option
常用的參數(shù)如下所示:
-
host
:請求網(wǎng)站的域名或 IP 地址蜘腌。 -
port
:請求網(wǎng)站的端口沫屡,默認(rèn)80
。 -
method
:請求方法撮珠,默認(rèn)是GET
沮脖。 -
path
:請求的相對于根的路徑金矛,默認(rèn)是/
。QueryString
應(yīng)該包含在其中勺届。例如/search?query=byvoid
驶俊。 -
headers
:一個(gè)關(guān)聯(lián)數(shù)組對象,為請求頭的內(nèi)容免姿。
http.get(options, callback)
: http
模塊還提供了一個(gè)更加簡便的方法用于處理GET
請求:http.get
饼酿。它是 http.request
的簡化版,唯一的區(qū)別在于http.get
自動(dòng)將請求方法設(shè)為了 GET
請求胚膊,同時(shí)不需要手動(dòng)調(diào)用 req.end()
故俐。
Chap4-19.js
var http=require('http');
http.createServer(function (req,res) {
res.writeHead(200,{"Content-Type":"text/html;charset=utf-8"});
//get 請求外網(wǎng)
var html='';
http.get('http://www.njfu.edu.cn',function(req1,res1){
req1.on('data',function(data){
html+=data;
});
req1.on('end',function(){
res.end(html);
});
});
}).listen(3000);
console.log("HTTP server is listening at port 3000.");
Chap4-20.js
var http=require('http');
var querystring=require('querystring');
http.createServer(function (req,res) {
res.writeHead(200,{"Content-Type":"text/html;charset=utf-8"});
//發(fā)送 http Post 請求
var postData=querystring.stringify({
msg:'中文內(nèi)容'
});
var options={
hostname:'www.njfu.edu.cn',
port:80,
path:'/',
method:'POST',
headers:{
'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
'Content-Length':Buffer.byteLength(postData)
}
};
var html='';
var req1=http.request(options, function(res1) {
res1.setEncoding('utf-8');
res1.on('data',function(chun){
html+=chun;
});
res1.on('end',function(){
res.end(html);
});
});
req1.write(postData); // write data to request body
req1.end();
}).listen(3000);
console.log("HTTP server is listening at port 3000.");
Express框架
- Express框架概述
- 路由
- 模板引擎
- 數(shù)據(jù)庫集成
Express框架概述
Express 是一個(gè)簡潔而靈活的 node.js Web應(yīng)用框架, 提供了一系列強(qiáng)大特性幫助你創(chuàng)建各種 Web 應(yīng)用,和豐富的 HTTP 工具紊婉。Express 作為開發(fā)框架药版,因?yàn)樗悄壳白罘€(wěn)定、使用最廣泛喻犁,而且 Node.js 官方推薦的唯一一個(gè) Web 開發(fā)框架槽片。
使用 Express 可以快速地搭建一個(gè)完整功能的網(wǎng)站。Express 框架核心特性:
- 可以設(shè)置中間件來響應(yīng) HTTP 請求肢础。
- 定義了路由表用于執(zhí)行不同的 HTTP 請求動(dòng)作还栓。
- 可以通過向模板傳遞參數(shù)來動(dòng)態(tài)渲染 HTML 頁面。
準(zhǔn)備工作
-
安裝Express:
npm install express -g //全局安裝 npm install express-generator -g //安裝全局變量
-
初始化項(xiàng)目:
cd example //進(jìn)入項(xiàng)目文件夾 express project //創(chuàng)建express目錄,project是目錄名
-
執(zhí)行如下命令:
cd project //進(jìn)入項(xiàng)目根目錄 npm install //安裝依賴
最終目錄:
- /bin:用來啟動(dòng)應(yīng)用(服務(wù)器)
- node_modules:存放 package.json 中安裝的模塊乔妈,當(dāng)你在 package.json 添加依賴的模塊并安裝后蝙云,存放在這
- /public:存放靜態(tài)資源(image、css路召、js)目錄
- /routes:路由用于確定應(yīng)用程序如何響應(yīng)對特定端點(diǎn)的客戶機(jī)請求勃刨,包含一個(gè) URI(或路徑)和一個(gè)特定的 HTTP 請求方法(GET、POST 等)股淡。每個(gè)路由可以具有一個(gè)或多個(gè)處理程序函數(shù)身隐,這些函數(shù)在路由匹配時(shí)執(zhí)行。
- /views:模板文件所在目錄
- app.js程序:main文件唯灵,這個(gè)是服務(wù)器啟動(dòng)的入口
- package.json:存儲(chǔ)著工程的信息及模塊依賴贾铝,當(dāng)在
dependencies
中添加依賴的模塊時(shí),運(yùn)行npm install
app.js節(jié)略
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
// 路由信息(接口地址)埠帕,存放在routes的根目錄
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
// 模板開始
app.set('views', path.join(__dirname, 'views'));
app.engine('.html', require('ejs').__express);
app.set('view engine', 'html');
//略
//配置路由垢揩,('自定義路徑',上面設(shè)置的接口地址)
app.use('/', indexRouter);?app.use('/users', usersRouter);
安裝ejs
模塊:npm install ejs
index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.type("text/html");
res.render("home",{pic:"images/njfu.jpg"}); //重要
});
module.exports = router;
users.js
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.type("text/html");
res.send('<h1>Welcome to Nanjing Forestry University</h1>');
});
module.exports = router;
home.html
<body class="HolyGrail">
<header>
<img src=<%=pic%> width="100%" height="200">
<!-- <%= pic %> 的標(biāo)簽敛瓷,功能是顯示引用的變量叁巨,即 res.render 函數(shù)第二個(gè)參數(shù)傳入的對象的屬性。-->
</header>
<div class="HolyGrail-body">
<div class="HolyGrail-nav">
<ul>
…
</ul>
</div>
<div class="HolyGrail-content">
<h1 style="text-indent: 20px">南林新聞</h1>
<ul>
…
</ul>
</div>
</div>
<footer>
<h5>版權(quán)所有 ? 2003-2012 南京林業(yè)大學(xué) 保留所有權(quán)利 地址:南京市龍?bào)绰?59號(hào)</h5>
</footer>
</body>
啟動(dòng)服務(wù)器:npm start
啟動(dòng)完成后終端將輸出 node ./bin/www
在瀏覽器中訪問 http://localhost:3000/
呐籽、http://localhost:3000/users
Express網(wǎng)站的架構(gòu)
瀏覽器發(fā)起請求锋勺,由路由控制器接受蚀瘸,根據(jù)不同的路徑定向到不同的控制器∈鳎控制器處理用戶的具體請求纳击,可能會(huì)訪問數(shù)據(jù)庫中的對象徽级,即模型部分底扳」烁矗控制器還要訪問模板引擎,生成視圖的 HTML布近,最后再由控制器返回給瀏覽器垫释,完成一次請求丝格。
路由
路由是指如何定義應(yīng)用的端點(diǎn)(URIs)以及如何響應(yīng)客戶端的請求撑瞧。
路由是由一個(gè) URI、HTTP 請求(GET显蝌、POST等)和若干個(gè)句柄組成预伺,它的結(jié)構(gòu)如下:
router.METHOD(path, [callback...], callback)
-
router
是express.Router
對象的一個(gè)實(shí)例,Router
實(shí)例是一個(gè)完整的中間件和路由系統(tǒng)曼尊。 -
METHOD
是一個(gè) HTTP 請求方法酬诀,如GET
、POST
等骆撇。 -
path
是服務(wù)器上的路徑瞒御。 -
callback
是當(dāng)路由匹配時(shí)要執(zhí)行的函數(shù)。
// GET method route
router.get('/', function (req, res) {
res.send('GET request to the homepage');
});
// POST method route
router.post('/', function (req, res) {
res.send('POST request to the homepage');
});
路由路徑
路由路徑和請求方法一起定義了請求的端點(diǎn)神郊,它可以是字符串肴裙、字符串模式或者正則表達(dá)式。
// 匹配根路徑的請求
router.get('/', function (req, res) {
res.send('root');
});
// 匹配 /about 路徑的請求
router.get('/about', function (req, res) {
res.send('about');
});
// 匹配 /random.text 路徑的請求
router.get('/random.text', function (req, res) {
res.send('random.text');
});
// 匹配 acd 和 abcd
router.get('/ab?cd', function(req, res) {
res.send('ab?cd');
});
// 匹配 abcd涌乳、abbcd蜻懦、abbbcd等
router.get('/ab+cd', function(req, res) {
res.send('ab+cd');
});
// 匹配 abcd、abxcd夕晓、abRABDOMcd宛乃、ab123cd等
router.get('/ab*cd', function(req, res) {
res.send('ab*cd');
});
// 匹配 /abe 和 /abcde
router.get('/ab(cd)?e', function(req, res) {
res.send('ab(cd)?e');
});
路由句柄
可以為請求處理提供多個(gè)回調(diào)函數(shù),其行為類似中間件蒸辆。唯一的區(qū)別是這些回調(diào)函數(shù)有可能調(diào)用 next('route')
方法而略過其他路由回調(diào)函數(shù)征炼。可以利用該機(jī)制為路由定義前提條件躬贡,如果在現(xiàn)有路徑上繼續(xù)執(zhí)行沒有意義谆奥,則可將控制權(quán)交給剩下的路徑。
路由句柄有多種形式逗宜,可以是一個(gè)函數(shù)雄右、一個(gè)函數(shù)數(shù)組空骚,或者是兩者混合。
app.js節(jié)略
// 路由信息(接口地址)擂仍,存放在routes的根目錄
var chap422Router = require('./routes/chap4-22');
//配置路由囤屹,('自定義路徑',上面設(shè)置的接口地址)
app.use("/chap4-22",chap422Router);
chap4-22.js
var express = require('express');
var router = express.Router();
router.get('/a', function (req, res) {
res.type("text/html");
res.send('<h1>Hello from A!</h1>');
});
router.get('/b', function (req, res, next) {
console.log('response will be sent by the next function ...');
next();
}, function (req, res) {
res.type("text/html");
res.send('<h1>Hello from B!</h1>');
});
var cb0 = function (req, res, next) {
console.log('CB0');
next();
};
var cb1 = function (req, res, next) {
console.log('CB1');
next();
};
var cb2 = function (req, res) {
res.type("text/html");
res.send('<h1>Hello from C!</h1>');
};
router.get('/c', [cb0, cb1, cb2]);
router.get('/d', [cb0, cb1], function (req, res, next) {
console.log('response will be sent by the next function ...');
next();
}, function (req, res) {
res.type("text/html");
res.send('<h1>Hello from D!</h1>');
});
module.exports = router;
響應(yīng)方法
響應(yīng)對象(res
)的方法向客戶端返回響應(yīng)逢渔,終結(jié)請求響應(yīng)的循環(huán)肋坚。如果在路由句柄中一個(gè)方法也不調(diào)用,來自客戶端的請求會(huì)一直掛起肃廓。
res.download(path [, filename] [, callback])
方法使用res.sendfile()
傳輸文件智厌。
-
path
:所需傳輸文件的路徑(絕對路徑),通常情況下瀏覽器會(huì)彈出一個(gè)下載文件的窗口盲赊。 -
filename
:指定下載文件窗口中顯示的默認(rèn)文件名稱铣鹏。
app.js節(jié)略
app.get("/download",function (req, res) {
var q = req.query;
if (q.type == "jpg") {
res.download(__dirname + "/public/images/njfu.jpg", "南林.jpg");
} else if (q.type == "txt") {
res.download(__dirname + "/public/files/content.txt");
} else {
res.send("錯(cuò)誤的請求");
}
});
res.end([data] [, encoding])
方法終結(jié)響應(yīng)處理流程。
res.json([body])
方法發(fā)送一個(gè)json的響應(yīng)哀蘑。這個(gè)方法和將一個(gè)對象或者一個(gè)數(shù)組作為參數(shù)傳遞給res.send()方法的效果相同诚卸。
res.redirect([status,] path)
方法發(fā)送重定向請求。
-
status: {Number}
绘迁,表示要設(shè)置的HTTP狀態(tài)碼合溺,如果不指定http狀態(tài)碼,使用默認(rèn)的狀態(tài)碼302
:"Found" -
path: {String}
缀台,要設(shè)置到Location
頭中的URL
res.send([body])
方法發(fā)送各種類型的響應(yīng)棠赛。
res.render(view [, option] [, callback(err,html)])
方法渲染視圖模板(view),并將渲染后的HTML字符串發(fā)送到客戶端膛腐。
-
view
:視圖模板文件名睛约,默認(rèn)在views文件夾下面; -
option
:對象依疼,指定返回的數(shù)據(jù)痰腮; -
callback(err,html)
:回調(diào)函數(shù),err
返回錯(cuò)誤信息律罢,html
返回渲染的HTML字符串膀值。注意:如果指定了回調(diào)函數(shù),則服務(wù)器端不會(huì)自動(dòng)將HTML字符串發(fā)送到客戶端误辑,需要用res.send()
方法發(fā)送茬缩。
app.js節(jié)略
// 路由信息(接口地址)芒篷,存放在routes的根目錄
var chap423Router = require('./routes/chap4-23');
//配置路由搜变,('自定義路徑',上面設(shè)置的接口地址)
app.use("/chap4-23",chap423Router);
chap4-23.js
var express = require('express');
var url = require('url');
var router = express.Router();
router.get('/redirect', function (req, res) {
res.redirect("/chap4-22/a");
});
router.get('/end', function (req, res) {
res.type("text/html");
res.end("<h1>終結(jié)響應(yīng)處理流程</h1>");
});
router.get('/json', function (req, res) {
res.json({user:"Zhangsan",password:"123456"});
});
router.get('/render', function (req, res) {
var newpath=url.resolve(req.url,"/images/njfu.jpg");
res.render("home",{pic:newpath},function (err,html) {
if(err){
console.error(err);
}else{
res.send(html);
}
});
});
module.exports = router;
請求方法
request
是瀏覽器給服務(wù)器的請求针炉,一般用到的是兩種方法:post
和get
挠他,兩種方法都會(huì)指定路由。request
提供了三種方法來獲取參數(shù)和內(nèi)容:request.params
篡帕,request.query
殖侵,request.body
。
-
request.body
返回post
方式傳送的內(nèi)容(名稱數(shù)值對)镰烧;app.js節(jié)略
// 路由信息(接口地址)拢军,存放在routes的根目錄 var chap426Router = require('./routes/chap4-26'); //ejs模板 app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); //配置路由,('自定義路徑'怔鳖,上面設(shè)置的接口地址) app.use("/chap4-26",chap426Router);
chap4-26.js
var express = require('express'); var router = express.Router(); router.get('/', function(req, res, next) { res.render('chap4-26'); }); router.post('/add', function (req, res) { res.type("text/html"); res.write('<h1>姓名:'+req.body.name+'</h1>'); res.write('<h1>年齡:'+req.body.age+'</h1>'); res.end('<h1>職業(yè):'+req.body.professional+'</h1>'); }); module.exports = router;
chap4-26.ejs
<div> <form action="/chap4-26/add" method="post"> 姓名:<input type="text" name="name"> 年齡:<input type="text" name="age"> 職業(yè):<input type="text" name="professional"> <input type="submit" value="post提交"> </form> </div>
-
request.query
返回get方式傳送的內(nèi)容茉唉,即獲取URL中?
后的名稱數(shù)值對;chap4-26.ejs
<div> <form action="/chap4-26/add1" method="get"> 姓名:<input type="text" name="name1"> 年齡:<input type="text" name="age1"> 職業(yè):<input type="text" name="professional1"> <input type="submit" value="get提交"> </form> </div>
chap4-26.js
router.get('/add1', function (req, res) { res.type("text/html"); res.write('<h1>姓名:'+req.query.name1+'</h1>'); res.write('<h1>年齡:'+req.query.age1+'</h1>'); res.end('<h1>職業(yè):'+req.query.professional1+'</h1>'); });
-
request.params
返回從express路由器獲取的參數(shù)结执。chap4-26.ejs
<div> <a href="/chap4-26/Update/zhangsan">修改</a> </div>
chap4-26.js
router.get('/Update/:name', function (req, res) { res.type("text/html"); res.send('<h1>姓名:'+req.params.name+'</h1>'); });
模板引擎
模板引擎(Template Engine)是一個(gè)從頁面模板根據(jù)一定的規(guī)則生成 HTML 的工具度陆。在 MVC 架構(gòu)中,模板引擎包含在服務(wù)器端献幔《控制器得到用戶請求后,從模型獲取數(shù)據(jù)蜡感,調(diào)用模板引擎蹬蚁。模板引擎以數(shù)據(jù)和頁面模板為輸入,生成 HTML 頁面铸敏,然后返回給控制器缚忧,由控制器交回客戶端。
基于 JavaScript 的模板引擎有許多種實(shí)現(xiàn)杈笔,我們推薦使用 ejs(Embedded JavaScript)闪水,因?yàn)樗趾唵危遗c Express 集成良好。由于它是標(biāo)準(zhǔn) JavaScript 實(shí)現(xiàn)的球榆,因此它不僅可以運(yùn)行在服務(wù)器端朽肥,還可以運(yùn)行在瀏覽器中。
在 app.js 中通過以下兩個(gè)語句設(shè)置了模板引擎和頁面模板的位置:
app.js節(jié)略
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
ejs 的標(biāo)簽系統(tǒng)非常簡單持钉,它只有以下3種標(biāo)簽衡招。
-
<% code %>
:JavaScript 代碼。 -
<%= code %>
:顯示替換過 HTML 特殊字符的內(nèi)容每强。 -
<%- code %>
:顯示原始 HTML 內(nèi)容始腾。
chap4-24.ejs
<h1><%=title%></h1>
<p>Welcome to <%=title%></p>
chap4-24.js
var express = require('express');
var router = express.Router();
router.use("/",function (req, res, next) {
res.render("chap4-24",{title:"Express"});
});
module.exports = router;
app.js節(jié)略
// 路由信息(接口地址),存放在routes的根目錄
var chap425Router = require('./routes/chap4-25');
// 模板開始
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
//配置路由空执,('自定義路徑'浪箭,上面設(shè)置的接口地址)
app.use("/chap4-25",chap425Router);
chap4-25.ejs
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>EJS模板</title>
<link rel="stylesheet" href="/stylesheets/chap4-25.css"/>
</head>
<body>
<h1>EJS模板引擎</h1>
<p>這是很簡單的一個(gè)小流程就不在一一的標(biāo)注流程了,注釋的很清楚了</p>
<p>這里是姓名: <span><%= name %></span></p>
<p>這里是性別: <span><%= sex %></span></p>
<p>這里是性別: <span><%= content %></span></p>
</body>
</html>
chap4-25.css
h1{ text-align: center;}
p{ font-size:20px;}
span{ font-size:25px; color: red;}
chap4-25.js
var express = require('express');
var router = express.Router();
var data={
name : 'webarn',
sex : '男',
content : '參數(shù),可以更改'
};
router.use("/",function (req, res, next) {
res.render("chap4-25",data);
});
module.exports = router;
集成數(shù)據(jù)庫
為 Express 應(yīng)用添加連接數(shù)據(jù)庫的能力,只需要加載相應(yīng)數(shù)據(jù)庫的 Node.js 驅(qū)動(dòng)即可辨绊。
MySQL模塊:npm install mysql
MySQL環(huán)境準(zhǔn)備
安裝MySQL時(shí)配置參數(shù):
- 服務(wù)器名:
localhost
(默認(rèn)) - 用戶名:
root
- 密碼:
0923
安裝結(jié)束后奶栖,打開MySQL Workbench,選擇要連接的服務(wù)器(localhost
)门坷,在當(dāng)前服務(wù)器中新建數(shù)據(jù)庫(例如宣鄙,educationdb
),在當(dāng)前數(shù)據(jù)庫中用create table
語句新建表格(例如:person
),并添加數(shù)據(jù)默蚌。
-- ----------------------------
-- Table structure for person
-- ----------------------------
CREATE TABLE `person` (
`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`name` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`professional` varchar(255) DEFAULT NULL,
)
-- ----------------------------
-- Records of person
-- ----------------------------
INSERT INTO `person` VALUES ('1', '武大', '25', '計(jì)算機(jī)科學(xué)與技術(shù)');
INSERT INTO `person` VALUES ('2', '王二', '25', '計(jì)算機(jī)科學(xué)與技術(shù)');
INSERT INTO `person` VALUES ('3', '張三', '25', '計(jì)算機(jī)科學(xué)與技術(shù)');
INSERT INTO `person` VALUES ('4', '李四', '25', '計(jì)算機(jī)科學(xué)與技術(shù)');
INSERT INTO `person` VALUES ('5', '孫五', '25', '計(jì)算機(jī)科學(xué)與技術(shù)');
INSERT INTO `person` VALUES ('6', '錢六', '25', '計(jì)算機(jī)科學(xué)與技術(shù)');
INSERT INTO `person` VALUES ('7', '趙七', '25', '計(jì)算機(jī)科學(xué)與技術(shù)');
INSERT INTO `person` VALUES ('8', '劉八', '25', '計(jì)算機(jī)科學(xué)與技術(shù)');
INSERT INTO `person` VALUES ('9', '張九', '25', '計(jì)算機(jī)科學(xué)與技術(shù)');
INSERT INTO `person` VALUES ('10', '鄭十', '25', '計(jì)算機(jī)科學(xué)與技術(shù)');
連接
mysql模塊是一個(gè)實(shí)現(xiàn)了MySQL協(xié)議的Node.js JavaScript客戶端冻晤,通過這個(gè)模塊可以與MySQL數(shù)據(jù)庫建立連接、執(zhí)行查詢等操作敏簿。
建立連接可以使用createConnection()
方法創(chuàng)建連接對象明也,再使用connect()
建立連接。
var mysql = require('mysql');
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '0923',
database: 'educationdb'
});
//可替換部分開始
connection.connect(function(err) {
if (err) {
return console.error('連接錯(cuò)誤: ' + err.stack);
}
console.log('連接ID ' + connection.threadId);
});
//可替換部分結(jié)束
建立連接也可以隱式的由查詢自動(dòng)創(chuàng)建:
可替換部分:
connection.query('SELECT * from person', function(err, rows) {
// 如果沒有錯(cuò)誤惯裕,則會(huì)連接成功!
});
在創(chuàng)建連接時(shí),需要傳入一些選項(xiàng)绣硝◎呤疲可傳入的選項(xiàng)參數(shù)如下:
-
host
-連接主機(jī)名(默認(rèn)為localhost
) -
port
-連接端口號(hào)(默認(rèn)為3306
) -
user
-MySql連接用戶名 -
password
-MySql連接密碼 -
database
-要連接的數(shù)據(jù)庫 -
connectTimeout
-連接超時(shí)時(shí)間(默認(rèn)10000
毫秒)
關(guān)閉數(shù)據(jù)庫連接可以使用兩種方法。
-
通過
end()
方法鹉胖,在執(zhí)行結(jié)束后關(guān)閉連接:connection.end(function(err) { // The connection is terminated now });
-
使用
destroy()
方法握玛,這個(gè)方法會(huì)立即關(guān)閉連接套接字,且這個(gè)方法沒有回調(diào)函數(shù):connection.destroy();
連接池
數(shù)據(jù)庫連接是一種有限的甫菠,能夠顯著影響到整個(gè)應(yīng)用程序的伸縮性和健壯性的資源挠铲,在多用戶的網(wǎng)頁應(yīng)用程序中體現(xiàn)得尤為突出。
數(shù)據(jù)庫連接池正是針對這個(gè)問題提出來的寂诱,它會(huì)負(fù)責(zé)分配拂苹、管理和釋放數(shù)據(jù)庫連接:允許應(yīng)用程序重復(fù)使用一個(gè)現(xiàn)有的數(shù)據(jù)庫連接,而不是重新建立一個(gè)連接痰洒;釋放空閑時(shí)間超過最大允許空閑時(shí)間的數(shù)據(jù)庫連接瓢棒,從而避免因?yàn)檫B接未釋放而引起的數(shù)據(jù)庫連接遺漏见秤。
數(shù)據(jù)庫連接池能明顯提高對數(shù)據(jù)庫操作的性能描函。
連接池連接時(shí)通過createPool()
方法可以使用連接池連接。
當(dāng)使用完連接池,要關(guān)閉所有連接浙于,可以使用end()
方法關(guān)閉連接池中的所有連接:
pool.end(function (err) {
// all connections in the pool have ended
});
通過getConnection()
方法連接可以共享一個(gè)連接,或管理多個(gè)連接勇皇。
連接使用完后通過調(diào)用connection.release()
方法可以將連接返回到連接池中佛呻,這個(gè)連接可以被其它人重復(fù)使用。
connection.release()
方法并不會(huì)將連接從連接池中移除跺撼,如果需要關(guān)閉連接且從連接池中移除翠语,可以使用connection.destroy()
。
db.js
// 數(shù)據(jù)庫包
var mysql = require(‘mysql’);
var pool = mysql.createPool({
host: ‘localhost’,
user: ‘root’,
password: ‘0923’,
database: ‘educationdb’
});
function query(sql, callback) {
pool.getConnection(function (err, connection) {
// Use the connection
connection.query(sql, function (err, rows) {
callback(err, rows);
connection.release();//釋放連接
});
});
}
exports.query = query;
執(zhí)行SQL語句
對數(shù)據(jù)庫的操作都是通過SQL語句實(shí)現(xiàn)的财边,通過SQL語句可以實(shí)現(xiàn)創(chuàng)建數(shù)據(jù)庫肌括、創(chuàng)建表、及對表中數(shù)據(jù)庫的增/刪/改/查等操作酣难。
執(zhí)行查詢:在node-mysql
中谍夭,通過Connection
或Pool
實(shí)例的query()
執(zhí)行SQL語句,所執(zhí)行的SQL語句可以是一個(gè)SELECT
查詢或是其它數(shù)據(jù)庫操作憨募。query()
方法有以下三種形式:
-
connection.query(sqlString, function(err,results,fields))
-
sqlString
:要執(zhí)行的SQL語句紧索; -
results
:為查詢結(jié)果; -
fields
:包含查詢結(jié)果的字段信息菜谣。
connection.query('SELECT * FROM `books` WHERE `author` = "David"', function (error, results, fields){});
-
-
connection.query(sqlString, values, function(err,results,fields))
-
values
:數(shù)組珠漂,表示要應(yīng)用到查詢占位符的值:
connection.query('SELECT * FROM `books` WHERE `author` = ?', ['David'], function (error, results, fields){});
var post = {id: 1, title: 'Hello MySQL'}; var query = connection.query('INSERT INTO posts SET ?', post, function(err, result) { //... }); console.log(query.sql); // INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL‘ //標(biāo)識(shí)符也可以使用??標(biāo)識(shí)符占位符 var userId = 1; var columns = ['username', 'email']; var query = connection.query('SELECT ?? FROM ?? WHERE id = ?', [columns, 'users', userId], function(err, results) { // ... }); console.log(query.sql); // SELECT `username`, `email` FROM `users` WHERE id = 1
-
-
connection.query(options, function(err,results,fields))
-
options
:對象,表示查詢選項(xiàng)參數(shù)connection.query({ sql: 'SELECT * FROM `books` WHERE `author` = ?', values: ['David'] }, function (error, results, fields) {});
-
當(dāng)使用參數(shù)占位符時(shí)尾膊,第二種和第三種形式也可以結(jié)合使用媳危。如:
connection.query({ sql: 'SELECT * FROM `books` WHERE `author` = ?', }, ['David'], function (error, results, fields) {});
-
app.js節(jié)略
// 路由信息(接口地址),存放在routes的根目錄
var persons = require('./routes/person');
//ejs模板
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
//配置路由冈敛,('自定義路徑'待笑,上面設(shè)置的接口地址)
app.use("/persons",persons);
person.js
var express = require('express');
var router = express.Router();
var db = require("./db.js"); //引入數(shù)據(jù)庫包
router.get('/', function (req, res, next) {
db.query('select * from person', function (err, rows) {
if (err) {
res.render('persons', {title: '人員管理', datas: []});
} else {
res.render('persons', {title: '人員管理', datas: rows});
}
})
});
//刪除
router.get('/del/:id', function (req, res) {
var id = req.params.id;
db.query("delete from person where id=" + id, function (err, rows) {
if (err) {
res.end('刪除失敗:' + err)
} else {
res.redirect('/persons')
}
});
});
//新增
router.get('/add', function (req, res) {
res.render('add');
});
router.post('/add', function (req, res) {
var name = req.body.name;
var age = req.body.age;
var professional = req.body.professional;
db.query("insert into person(name,age,professional) values('" + name + "'," + age + ",'" + professional + "')", function (err, rows) {
if (err) {
res.end('新增失斪デ础:' + err);
} else {
res.redirect('/persons');
}
})
});
//修改
router.get(‘/toUpdate/:id’, function (req, res) {
var id = req.params.id;
db.query(“select * from person where id=” + id, function (err, rows) {
if (err) {
res.end(‘修改頁面跳轉(zhuǎn)失斈乎濉:’ + err);
} else {
res.render(“update”, {datas: rows}); //直接跳轉(zhuǎn)
}
});
});
router.post('/update', function (req, res) {
var id = req.body.id;
var name = req.body.name;
var age = req.body.age;
var professional = req.body.professional;
db.query("update person set name='" + name + "',age='" + age + "',professional= '" + professional + "' where id=" + id, function (err, rows) {
if (err) {
res.end('修改失敗:' + err);
} else {
res.redirect('/persons');
}
});});
//查詢
router.post('/search', function (req, res) {
var name = req.body.s_name;
var age = req.body.s_age;
var professional = req.body.s_professional;
var sql = "select * from person";
if (name) {
sql += " and name like '%" + name + "%' ";
}
if (age) {
sql += " and age=" + age + " ";
}
if (professional) {
sql += " and professional like '%" + professional + "%' ";
}
sql = sql.replace("person and","person where");
db.query(sql, function (err, rows) {
if (err) {
res.end("查詢失敯┭埂:", err)
} else {
res.render("persons", {title: '人員管理', datas: rows});
}
});});
module.exports = router;
persons.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title><%= title %></title>
<style>
div{width:800px;margin: 0 auto;}
table {border-collapse:collapse;border-spacing:0;width:800px;}
table tr td ,table tr th {border-top:solid 1px #ccc;border-left:solid 1px #ccc;line-height: 40px;text-align: center;}
table tr td:last-child, table tr th:last-child {border-right:solid 1px #ccc;}
table tr:last-child td{border-bottom:solid 1px #ccc;}
a{text-decoration: none;font-size: 14px;}
.text{width:150px;}
</style>
</head>
<body>
<div>
<div style="">
<div style="float: left;width:10%;">
<a href="/persons/add">新增</a>
</div>
<div style="float: right;width:90%;">
<form action="/persons/search" method="post">
姓名:<input type="text" name="s_name" value="" class="text">
年齡:<input type="text" name="s_age" value="" class="text">
職業(yè):<input type="text" name="s_professional" value="" class="text">
<input type="submit" value="查詢">
</form>
</div>
</div>
<table style="">
<tr>
<th width="10%">編號(hào)</th>
<th width="15%">操作</th>
<th width="15%">姓名</th>
<th width="10%">年齡</th>
<th width="50%">職業(yè)</th>
</tr>
<% if (datas.length) { %>
<% datas.forEach(function(person){ %>
<tr>
<td><%= person.id %></td>
<td><a href="/persons/del/<%= person.id %>">刪除</a> <a href="/persons/toUpdate/<%= person.id %>">修改</a></td>
<td><%= person.name %></td>
<td><%= person.age %></td>
<td><%= person.professional %></td>
</tr>
<% }) %>
<% } %>
</table>
</div>
</body>
</html>
add.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>新增頁面</title>
</head>
<body>
<div style="width: 800px;margin: auto;">
<form action="/persons/add" method="post">
姓名:<input type="text" name="name">
年齡:<input type="text" name="age">
職業(yè):<input type="text" name="professional">
<input type="submit" value="提交">
</form>
</div>
</body>
</html>
update.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>修改頁面</title>
</head>
<body>
<div style="width: 800px;margin: auto;">
<form action="/persons/update" method="post">
<input type="hidden" value="<%= datas[0].id %>" name="id">
姓名:<input type="text" name="name" value="<%= datas[0].name %>">
年齡:<input type="text" name="age" value="<%= datas[0].age %>">
職業(yè):<input type="text" name="professional" value="<%= datas[0].professional %>">
<input type="submit" value="提交">
</form>
</div>
</body>
</html>