第一章 JavaScript 簡史
主要講了JavaScript的起源和發(fā)展.
第二章 JavaScript語法
2.1 準(zhǔn)備工作
2.2 語法
2.2.1 語句
如果你想把多條語句放在同一行上,就必須用分號來分隔開它們。
2.2.2 注釋
- //自我提醒:有注釋是好事
- /*自我提醒:
有注釋是好事
2.2.3 變量
- javascript允許程序員直接對變量賦值而無需事先聲明
- 不允許變量名中包含空格或標(biāo)點(diǎn)符號(美元符號”$"例外)
- 一般使用駝峰格式來起變量的名字
2.2.4 數(shù)據(jù)類型
1.字符串
2.數(shù)值
3.布爾值
2.2.5 數(shù)組
2.2.6對象
2.3 操作
-
算術(shù)操作符
加號(+)是一個(gè)比較特殊的操作符,它即可以用于數(shù)值,也可以用于字符串
2.4 條件語句
-
比較操作符
-
邏輯操作符
2.5 循環(huán)語句
-
while循環(huán)
-
for循環(huán)
2.6 函數(shù)
變量的作用域
如果在某個(gè)函數(shù)中使用了var,那個(gè)變量就將被視為一個(gè)局部變量,它只存在于這個(gè)函數(shù)的上下文中;反之,如果沒有使用var,那個(gè)變量就將被視為一個(gè)全局變量。
2.7 對象
-
內(nèi)建對象
包括Array對象,Math對象和Date對象
-
宿主對象
由瀏覽器提供的預(yù)定義對象被稱為宿主對象,包括Form、Image和Element等。
第三章 DOM
3.1 文檔:DOM中的"D"
3.2 對象:DOM中的"O"
3.3 模型:DOM中的"M"
3.4 節(jié)點(diǎn)
-
元素節(jié)點(diǎn)
-
文本節(jié)點(diǎn)
-
屬性節(jié)點(diǎn)
-
獲取元素
1.getElementById
- 返回一個(gè)與那個(gè)有著給定id屬性值的元素節(jié)點(diǎn)對應(yīng)的對象
- 它是document對象特有的函數(shù)
- 可以通過typeof操作符在確定操作數(shù)是一個(gè)字符串、數(shù)組、函數(shù)、布爾值還是對象。
2.getElementsByTagName
- 返回一個(gè)對象數(shù)組,每個(gè)對象分別對應(yīng)著文檔里有著給定標(biāo)簽的一個(gè)元素。
- 運(yùn)行把一個(gè)通配符"*"作為它的參數(shù)。
3.getElementsByClassName
- 返回一個(gè)與那個(gè)有著給定class屬性值的元素節(jié)點(diǎn)對應(yīng)的對象
3.5 獲取和設(shè)置屬性
1.getAttribute(attribute)
2.setAttribute(attribute,value)
第三章 JavaScript圖片庫
第五章 最佳實(shí)踐
第六章 圖片庫的改進(jìn)版
第四章將html,css與javascript運(yùn)用到了JavaScript圖片庫上
- 為了減少對站點(diǎn)的請求次數(shù)(提高性能),應(yīng)該把這些.js文件合并到一個(gè)文件中;
- 事件處理函數(shù):在特定事件發(fā)生時(shí),調(diào)用特定的JavaScriptd代碼;
- nodeValue屬性:用來得到和設(shè)置一個(gè)節(jié)點(diǎn)的值;
- 包含在<p>元素里的文本是另一個(gè)節(jié)點(diǎn),它是<p>元素的第一個(gè)子節(jié)點(diǎn);
- firstChild和lastChild屬性,子節(jié)點(diǎn)的第一個(gè)和最后一個(gè)元素;
- childNodes屬性:可以用來獲取任何一個(gè)元素的所有子元素,是一個(gè)包含這個(gè)元素全部子元素的數(shù)組;
- onload事件處理函數(shù):函數(shù)在頁面加載時(shí)執(zhí)行;
- nodeType屬性:返回節(jié)點(diǎn)的類型;
事件處理函數(shù)的工作機(jī)制:
以onclick為例:我們給某個(gè)鏈接添加一個(gè)onclick事件處理函數(shù),并讓這個(gè)處理函數(shù)所觸發(fā)的js代碼返回布爾值true或false,這樣一來,當(dāng)這個(gè)鏈接被點(diǎn)擊時(shí),如果那段js代碼返回的值是true,onclick事件處理函數(shù)就認(rèn)為被點(diǎn)擊了;反之,則沒有被點(diǎn)擊。
節(jié)點(diǎn)的類型總共有12種可取值,有3種具有實(shí)用價(jià)值:
- 元素節(jié)點(diǎn)的nodeType屬性值是1
- 屬性節(jié)點(diǎn)的nodeType屬性值是2
- 文本節(jié)點(diǎn)的nodeType屬性值是3
第五章介紹了最佳實(shí)踐
在本章作者提出了一些好的網(wǎng)站應(yīng)該滿足的要求:
1、在使用任何一句javascript代碼時(shí),都應(yīng)該想想,對這個(gè)網(wǎng)頁是否有用;
2、平穩(wěn)退化:如果正確使用了javascript腳本,可以讓訪問者在他們的瀏覽器不支持javascript的情況下仍能順利地瀏覽你網(wǎng)站。雖然某些功能無法使用,但是最基本的操作仍能順利完成;
3、漸進(jìn)增強(qiáng):用額外的信息層區(qū)包裹原始數(shù)據(jù);使CSS代碼負(fù)責(zé)提供關(guān)于表示的信息,javascript代碼負(fù)責(zé)提供關(guān)于行為的信息;
4、分離javascript:在HTML文檔中使用諸如onclick之類的屬性也是一種沒有效率又容易引發(fā)問題的做法。如果利用像CSS中的class和id屬性那樣,把javascript代碼調(diào)用行為與HTML文檔內(nèi)容和結(jié)構(gòu)分離,網(wǎng)頁也會健壯不少。
5、向后兼容:對象檢測:檢測瀏覽器對javascript的支持程度。用一個(gè)if語句的條件表達(dá)式看求值結(jié)果是true還是false來采取不同的行動(dòng)。如在代碼前加上if(!getElementById) return false;
6、性能考慮:盡量少訪問DOM和盡量減少標(biāo)記
不管什么時(shí)候只要是查詢DOM中的某些元素,瀏覽器就會搜索整個(gè)DOM樹,從中查到可能匹配的元素。
在多個(gè)函數(shù)都會取得類似元素的情況下,可以考慮重新構(gòu)建代碼,把搜索結(jié)果保存在一個(gè)全局變量里,或者把一組元素以參數(shù)形式傳遞給函數(shù)。
減少標(biāo)記數(shù)量的目的在于,過多的不必要的元素只會增加DOM樹的規(guī)模;
7、合并和放置腳本:減少請求數(shù)量是在性能優(yōu)化時(shí)首先要考慮的;把所有<script>標(biāo)簽都放在文檔的末尾,</body>標(biāo)記之前,可以讓頁面變得更快。
8、壓縮腳本:指的是把腳本文件中的不必要的字節(jié),如空格和注釋,都刪除調(diào),從而達(dá)到“壓縮”文件的目的;多數(shù)情況下應(yīng)該有兩個(gè)版本,一個(gè)是工作副本,可以修改代碼并添加注釋,另一個(gè)是精簡副本,用于放在站點(diǎn)上,通常在精簡副本的文件名上加上min字樣;
一些新的概念:
1、“javascript"偽協(xié)議:真協(xié)議讓我們在因特網(wǎng)上的計(jì)算機(jī)之間傳輸數(shù)據(jù)包,偽協(xié)議是一種非標(biāo)準(zhǔn)化的協(xié)議,讓我們通過一個(gè)鏈接調(diào)用javascript函數(shù);
2、瀏覽器嗅探技術(shù):通過瀏覽器供應(yīng)商提供的信息來解決向后兼容的問題。
3、document對象是window對象的一個(gè)屬性,當(dāng)window對象觸發(fā)onload事件時(shí),document對象已經(jīng)存在,文檔樹就會被創(chuàng)建成功;
第六章對圖片庫進(jìn)行了優(yōu)化
以下是本章的一些其他要點(diǎn):
1、結(jié)構(gòu)化程序設(shè)計(jì)要求函數(shù)只有一個(gè)入口和出口。但只要出口集中出現(xiàn)在函數(shù)的開頭部分就是可以接受的。
2、每個(gè)事件處理函數(shù)只能綁定一條指令。
3、nodeName屬性總是返回一個(gè)大寫字母的值,即時(shí)元素在HTML文檔中是小寫字母。
4、鍵盤訪問:最好不要使用onkeypresss事件處理函數(shù),onclick事件處理函數(shù)已經(jīng)能滿足需要,它對鍵盤的訪問相當(dāng)完美
html代碼:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>javascript dom圖片庫</title>
<script src="javascript圖片庫.js"></script>
<style>
*{
margin:0;
padding:0;
}
body{
background-color:#ccc;
margin: 1em 10%;
}
h1 {
color:#333;
background-color:transparent;
}
li{
float:left;
padding: 1em;
list-style:none;
}
img,p{
display:block;
clear:both;
}
#imagegallery li{
display:inline;
}
#imagegallery li a img{
border:0;
width:100px;
height:100px;
}
</style>
</head>
<body>
<h1>Snapshots</h1>
<ul id="imagegallery">
<li>
<a href="images/1.jpg" title="a 1 display" class="showPic">

</a>
</li>
<li>
<a class="popup" title="a 2 display" onclick="popUP(this.getAttribute("href"));return false;">平穩(wěn)退化</a>
</li>
<li>
<a href="images/2.jpg" class="showPic" title="a 2 display">

</a>
</li>
<li>
<a href="images/3.jpg" class="showPic" title="a 3 display">

</a>
</li>
<li>
<a href="images/4.jpg" class="showPic" title="a 4 display">

</a>
</li>
</ul>
</body>
</html>
js代碼:
function addLoadEvent(func){
//把現(xiàn)在的window.onload事件處理函數(shù)的值存入變量oldload
var oldonload = window.onload;
if(typeof window.onload != "function"){
//如果在這個(gè)處理函數(shù)上還沒有綁定任何函數(shù),就按平時(shí)那樣把新函數(shù)添加給它。
window.onload = func;
} else{
window.onload = function(){
//如果在這個(gè)處理函數(shù)上已經(jīng)綁定了函數(shù),就把新函數(shù)添加到現(xiàn)有指令的末尾。
oldonload();
func();
}
}
}
addLoadEvent(preparePlaceholder);
addLoadEvent(prepareLinks);
//把占位符替換成想要的圖片
function showPic(whichpic){
//進(jìn)行對象檢測,向后兼容,利用結(jié)構(gòu)化程序設(shè)計(jì)中的“一個(gè)函數(shù)應(yīng)該只有一個(gè)入口和一個(gè)出口”
if(!document.getElementById){
if(!document.getElementsByTagName){
return false;
}
}
var source = whichpic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
var gallery = document.getElementById("imagegallery");
gallery.parentNode.insertBefore(placeholder,gallery);
placeholder.setAttribute("src",source);
if(document.getElementById("description")){//不要做太多假設(shè),當(dāng)description存在才執(zhí)行下面的代碼,如果不存在就忽略
var text = whichpic.getAttribute("title");
var description = document.getElementById("description");
description.firstChild.nodeValue = text;
//firstChild返回元素的第一個(gè)子元素
}
}
function popUP(winURL){
window.open(winURL,"popup","width:400,height:400");
}
//實(shí)現(xiàn)了javascript與html的分離
function prepareLinks(){
//盡量減少訪問DOM和盡量減少標(biāo)記,例如下面把document.getElementsByTagName("a")存放在變量links中,使得getElementsByTagName("a")只執(zhí)行了一次,后面只需要調(diào)用links;
if(!document.getElementsByTagName){
return false;
}
var links = document.getElementsByTagName("a");
if(links.length>0){
for(var i=0;i<links.length;i++){
if(links[i].getAttribute("class") == "showPic"){
links[i].onclick=function(){
//只有showPic函數(shù)執(zhí)行成功才返回true
showPic(this);
console.log(showPic(this));//輸出undefined
return false;
//想要阻止鏈接被點(diǎn)擊后的默認(rèn)行為,可以給點(diǎn)擊事件里面的javascript代碼返回一個(gè)布爾類型的值,true就代表被點(diǎn)擊了,false就代表沒有被點(diǎn)擊
}
}
}
}
}
function preparePlaceholder(){
var gallery = document.getElementById("imagegallery");
var placeholder = document.createElement("img");
placeholder.setAttribute("id","placeholder");
placeholder.setAttribute("alt","my image gallery");
var description = document.createElement("p");
description.setAttribute("id","description");
var desctext = document.createTextNode("Choose an image");
description.appendChild(desctext);
insertAfter(placeholder,gallery);
insertAfter(description,placeholder);
}
//在現(xiàn)有元素后插入一個(gè)新元素
function insertAfter(newElement,targetElement){
var parent = targetElement.parentNode;
//檢查targetElement是不是parent的最后一個(gè)子元素
if(parent.lastChild == targetElement){
//如果是就追加到parent元素上
parent.appendChild(newElement);
} else{
//如果不是,把新元素插入到目標(biāo)元素和目標(biāo)元素的下一個(gè)兄弟元素之間。其中目標(biāo)元素的下一個(gè)兄弟元素即目標(biāo)元素的nextSibling屬性。
parent.insertBefore(newElement,targetElement.nextSibling);
}
}
第七章 動(dòng)態(tài)創(chuàng)建標(biāo)記
本章首先回顧了創(chuàng)建標(biāo)記的方法:
一些傳統(tǒng)的方法:
1、document.write:
違背了“行為應(yīng)該與表現(xiàn)分離”的原則。
2、innerHTML:
并不是W3C DOM標(biāo)準(zhǔn)的組成部分,但是現(xiàn)在已經(jīng)包含到HTML5規(guī)范里面中了。
就本屬性看來,標(biāo)記下只有一個(gè)字符串,其無細(xì)節(jié)可言,會永久改變原來的文檔。比document.write()方法值得推薦,也是HTML專屬屬性,不能用于其他標(biāo)記語言文檔。
DOM方法:
1、只要用正確的方法,就可以獲取DOM節(jié)點(diǎn)樹上任何一個(gè)節(jié)點(diǎn)的細(xì)節(jié)。
2、改變顯示內(nèi)容,但不會改變物理內(nèi)容。
3、在瀏覽器看來,DOM節(jié)點(diǎn)才是文檔
4、createElement方法:
創(chuàng)建元素節(jié)點(diǎn),只創(chuàng)建會出現(xiàn)一個(gè)文檔碎片,它是游蕩在javascript世界里的一個(gè)孤兒。但是它已經(jīng)有nodeType和nodeName屬性
appendChild方法
createTextNode方法:創(chuàng)建文本節(jié)點(diǎn)
以上三種結(jié)合使用來擴(kuò)展文檔樹
parentElement.insertBefore(newElement,targetElement)
targetElement元素的parentNode屬性值就是parentElement;
屬性節(jié)點(diǎn)和文本節(jié)點(diǎn)的子元素不允許是元素節(jié)點(diǎn)
5、Ajax
使用Ajax可以做到只更新頁面中的一小部分,其他內(nèi)容不用重新加載,Ajax的主要優(yōu)勢是對頁面的請求以異步方式發(fā)送到服務(wù)器。
XMLHttpRequest對象
瀏覽器腳本與服務(wù)器之間的中間人的角色。javascript可以通過這個(gè)對象自己發(fā)送請求,同時(shí)自己處理響應(yīng)。
問題在于不同瀏覽器實(shí)現(xiàn)XMLHttpRequest對象的方式不太一樣。
該對象最有用的是open方法:用來指定服務(wù)器上將要訪問的文件,指定請求類型:GET、POST或SEND。
訪問服務(wù)器發(fā)送回來的數(shù)據(jù)要通過兩個(gè)屬性完成,一個(gè)是responseText屬性,這個(gè)屬性用于保存文本字符串形式的數(shù)據(jù),另一個(gè)屬性是responseXML屬性,用于保存Content-Type頭部中指定為text/xml的數(shù)據(jù)。
使用Ajax需要注意同源策略:使用XMLHttpRequest對象發(fā)送的請求只能訪問與其所在的HTML處于同一個(gè)域中的數(shù)據(jù),不能像其他域發(fā)送請求,有些瀏覽器會限制Ajax請求使用的協(xié)議。
異步性:腳本在發(fā)送XMLHttpRequest請求之后,仍然會繼續(xù)執(zhí)行,不會等待響應(yīng)返回。
本書推薦的三個(gè)自己構(gòu)建的函數(shù):insertAfter函數(shù):
function insertAfter(newElement,targetElement){
var parent=targetElement.parentNode;
if (parent.lastChild==targetElement){
parent.appendChild(newElement);
}else{ parent.insertBefore(newElement,targetElement.nextSibling);
}
}
加載函數(shù):
addLoadEvent(func){
var oldonload=window.onload;
if(typeof window.onload !=‘function’){
window.onload = func;
}else{
window.onload = function(){
oldonload(); func(); } }
}
添加類名:
function addClass(element,value){
if (!element.className) {
element.className=value;
}else{
newClassName =element.className; newClassName+=""; newClassName+=value; element.className=newClassName;
}
}