javascript
《JavaScript DOM 编程艺术》 读书笔记
概念:
- 平穩(wěn)退化
- 漸進增強
- 以用戶為中心
第一章 js簡史
可以使用DOM(Document Object Model)給HTML(HyperText Markup Language)文檔增加交互能力,就像CSS(Cascading Style Sheet)給文檔增加樣式一樣。DOM是一種API(Application Programing Interface),就是一種已得到各方認同的基本約定,作為一種標(biāo)準可以使得人們更方便的進行交流和合作,類似于化學(xué)元素周期表、莫爾斯碼,W3C聯(lián)盟推出的標(biāo)準化DOM理論上可以讓任何一種程序設(shè)計語言對使用任何一種標(biāo)記語言編寫出來的任何一份文檔進行操控。
W3C聯(lián)盟對DOM的定義:一個與系統(tǒng)平臺和編程語言無關(guān)的接口,程序和腳本可以通過這個接口動態(tài)的訪問和修改文檔的內(nèi)容、結(jié)構(gòu)和樣式。
第二章 js語法
準備工作
程序語言分為解釋型和編譯型兩大類
Java、C++等語言需要一個編譯器(Compiler)。編譯器是一種程序,能夠把用Java等解釋型高級語言編寫出來的源代碼翻譯為直接在計算機上執(zhí)行的文件。
編譯型的語言編寫的代碼如果有錯誤,這些錯誤會在代碼編譯階段就會被發(fā)現(xiàn)。與解釋型語言相比速度更快,可移植性更高,但學(xué)習(xí)曲線也更陡峭。
解釋型語言不需要編譯器,僅需要解釋器。對于JavaScript語言,在互聯(lián)網(wǎng)環(huán)境下Web瀏覽器負責(zé)完成有關(guān)的解釋和執(zhí)行工作。瀏覽器中的JavaScript解釋器將直接讀入源代碼并執(zhí)行。瀏覽器中如果沒有解釋器,JavaScript代碼就無法執(zhí)行。
解釋型語言編寫的代碼只能等到解釋器執(zhí)行到有關(guān)代碼時才能被發(fā)現(xiàn)。
語法
每行結(jié)尾并不一定需要分號,不過為了更容易追蹤JavaScript腳本的執(zhí)行順序還是推介加上;
var不關(guān)心變量的類型,ex:
字符串可以包括在雙引號或者單引號里,如果在引號中包括引號,那么需要對這個字符進行轉(zhuǎn)義(escaping):
var str="about 5'10\" tall";- 數(shù)組聲明:
- 對象聲明:
- 比較操作符:
相等操作符 == 會認為false與空字符串含義相同,如果要進行嚴格比較,則需要全等操作符 ===,全等操作符會執(zhí)行嚴格的比較,不僅會比較值,還會比較變量的類型,嚴格不相等也類似 !== 。ex:
var strC = false; if (strC === "") {alert("xixi"); //不會輸出 }在if()或者while()的判斷條件中,整數(shù)中0被判斷為false,除了0之外都為true包括負數(shù)。
while (-1.1) {alert("memeda"); //會一直輸出 }for循環(huán):
var beatles = ["John", "Paul", "George", "Ringo", true, 44, [0, false, "my Dog", strB]]; for (var strE = 0; strE < beatles.length; strE++) {alert(beatles[strE]); }函數(shù):
function shout(para) {var beatles = [para, 44];for (var strE = 0; strE < beatles.length; strE++) {alert(beatles[strE]);} } shout("xixixi"); //彈出2條alert: xixixi , 44變量和函數(shù)的命名(為了能一眼看出哪些是變量,哪些是函數(shù)):
- 變量使用下劃線來分割各個單詞,如temp_celsius;
- 函數(shù)名使用首字母小寫的駝峰命名法,如convertToCelsius;
內(nèi)建對象(Native Object):
- Array
- Math
- Date
etc...
第三章 DOM
DOM是針對XML但是經(jīng)過擴展用于HTML的應(yīng)用程序編程接口。DOM把整個頁面映射為一個多層節(jié)點結(jié)構(gòu)。
DOM中的D
D指的是document,當(dāng)創(chuàng)建了一個網(wǎng)頁并將其加載到web瀏覽器中時,DOM已經(jīng)被創(chuàng)建,它把編寫的網(wǎng)頁文檔轉(zhuǎn)換成一個文檔對象。
DOM中的O
O指的是對象object,js中的對象包括:
- 用戶自定義對象(user-defined object):自行創(chuàng)建的對象
- 內(nèi)建對象(native object):內(nèi)建在js中的對象,如Array、Math、Date
- 宿主對象(host object):由瀏覽器提供的對象
最基礎(chǔ)的宿主對象:window對象:
window.open("http://www.baidu.com", "","", false); //彈出百度窗口,也可以是新窗口DOM中的M
M指的是Model,有三種DOM方法可以獲取元素節(jié)點,分別是通過ID,通過標(biāo)簽名,和通過類名來獲取。
- getElementById
返回一個有著給定ID屬性值的元素節(jié)點對應(yīng)的對象,它是document對象特有的函數(shù),并且形參是要獲取的id值,放在單引號或雙引號里:
<h1 title="memeda" id="header_h1">Hello World!</h1> <script>alert(document.getElementById("header_h1").getAttribute("title")); //彈出 memeda </script>- getElementsByTagName
返回一個對象數(shù)組,每個對象對應(yīng)著文檔里有著給定標(biāo)簽的一個元素,形參是標(biāo)簽,且在引號內(nèi):
<ul><li>Data1</li><li>Data2</li><li>Data3</li> </ul> <script>alert(document.getElementsByTagName("li").length); //彈出 3 </script>- getElementsByClassName
返回具有Class名的對象數(shù)組,還可以查找那些帶有多個類名的元素,并不是所有瀏覽器都支持:
<ul><li class="data_1 data_2">Data1</li><li class="data_1">Data2</li><li class="data_2">Data3</li> </ul> <script>alert(document.getElementsByClassName("data_1 data_2").length); //彈出 1 ,只有一個元素既有data_1也有data_2 </script>如果瀏覽器不一定支持,那么可以使用:
function getElementsByClassName(node, classname) { //node是DOM樹中搜索起點,也可以是document,不支持多個class搜索if (node.getElementsByClassName) {return node.getElementsByClassName(classname);} else {var results = [];var elems = node.getElementsByTagName("*");for (var i = 0; i < elems.length; i++) {if (elems[i].className.indexOf(classname) != -1) {results[results.length] = elems[i];}}} }- getAttribute & setAttribute
可以用來獲取和設(shè)置節(jié)點的屬性:
<h1 title="memeda" id="header_h1">Hello World!</h1> <script>var shop=document.getElementById("header_h1");alert(shop.getAttribute("title"));shop.setAttribute("title","xixi");alert(shop.getAttribute("title")); </script>通過setAttribute對文檔作出修改后,通過查看源代碼發(fā)現(xiàn)文檔源代碼仍然是改變之前的值,也就是說,setAttribute作出的修改并不會反映到文檔本身的源代碼里,原因是DOM的工作模式:先加載文檔的靜態(tài)內(nèi)容,再動態(tài)刷新,動態(tài)刷新不影響文檔的靜態(tài)內(nèi)容。
這正是DOM的真正威力:對頁面內(nèi)容進行刷新卻不需要在瀏覽器里刷新頁面。
第四章 js圖片庫
需要說明的是,若一個站點要用到多個js文件,為了減少對站點的請求次數(shù)提高性能,應(yīng)該把這些js文件合并到一個文件中。圖片同理。
實例:
<ul><li><a href="../imgs/aaa.jpeg" onclick="showpic(this); return false;">Data1</a></li><li><a href="../imgs/step.png" onclick="showpic(this); return false;">Data2</a></li><li><a href="../imgs/arrow-right-bold.png" onclick="showpic(this); return false;">Data3</a></li><li><a href="../imgs/dazongdianpin_logo.png" onclick="showpic(this); return false;">Data4</a></li> </ul> <img id="placeholder" src="../imgs/CD.jpg" alt="My image gallery"><script>function showpic(whichpic) {document.getElementById("placeholder").setAttribute("src", whichpic.getAttribute("href"));} </script>實現(xiàn)一個在點擊a標(biāo)簽時把placeholder占位圖片替換成a標(biāo)簽對應(yīng)的圖片,并攔截點擊a時網(wǎng)頁的默認行為。
另外,setAttribute方法是DOM Level1 的內(nèi)容,它可以設(shè)置任意元素節(jié)點的任意屬性,在DOM Level1出現(xiàn)之前的HTML-DOM還可以通過:element.value="value"來直接設(shè)置元素的屬性,不過不推介使用這種方式,這種方式只適用于web文檔,而DOM則適用于任何一種標(biāo)記語言,因為“DOM是一種適用于多種環(huán)境和多種程序設(shè)計語言的通用型API”,比如xml,為了更好的移植性,嚴格遵守DOM Level1可以避免很多問題。
-
nodeType屬性可以得到任何節(jié)點的節(jié)點屬性:
- 元素節(jié)點的nodeType值為1
- 屬性節(jié)點的nodeType值為2
- 文本節(jié)點的nodeType值為3
- nodeValue屬性:
可以用來檢索節(jié)點的值,也可以用來設(shè)置節(jié)點的值。
<ul><li><a href="#" onclick="showa(this);return false;">xixi1</a></li><li><a href="#" onclick="showa(this);return false;">xixi2</a></li><li><a href="#" onclick="showa(this);return false;">xixi3</a></li> </ul> <p id="description">Hello</p> <script>function showa(whicha) {document.getElementById("description").firstChild.nodeValue = whicha.firstChild.nodeValue;} </script>第五章 最佳實踐
平穩(wěn)退化
平穩(wěn)退化(graceful degradation)確保網(wǎng)頁在沒有js的情況下也能正常工作;就是說,雖然某些功能無法使用,但最基本的操作仍能順利實現(xiàn)。
<a href="http://www.baidu.com/" onclick="openw(this.href);return false;">Example</a> <script>function openw(urlStr) {window.open(urlStr, "ppp", "width=400,height=600");} </script>這種方式比JavaScript偽協(xié)議:href="javascript:..."和href="#" onclick=“...”,方式效果要好得多,即使在js功能已被禁用或者遇到爬蟲的情況下,鏈接也是可用的,雖然功能上打了折扣,但是并沒有徹底失效。
漸進增強
漸進增強(progressive enhancement)原則基于這樣一種思想:實現(xiàn)良好的結(jié)構(gòu)應(yīng)該從最核心的部分,也就是從內(nèi)容開始。根據(jù)內(nèi)容使用標(biāo)記實現(xiàn)良好的結(jié)構(gòu);然后再逐步加強這些內(nèi)容,這些增強工作可以是通過css改進呈現(xiàn)效果,也可以通過DOM添加各種行為,如果使用DOM來添加核心內(nèi)容,那么這是不推介的,并且也不利于網(wǎng)站SEO,js也沒有任何空間去平穩(wěn)退化,那些缺乏js支持的訪問者就無法看到其內(nèi)容。
向后兼容
確保老版本的瀏覽器不會因為你的js而掛掉;
可以使用對象檢測(object detection):
檢測瀏覽器是否支持這一方法,來避免老版本瀏覽器不會因為新加入的js出錯。
分離js
把網(wǎng)頁的結(jié)構(gòu)和內(nèi)容與js腳本的動作行為分開;
性能考慮
確保腳本執(zhí)行的性能最優(yōu);
- 避免搜索浪費
這樣會進行兩次.getElementsByTagName()搜索,造成性能浪費,因此不推介。如果有多個函數(shù)重復(fù)做一件事,那么可以把搜索結(jié)果放在全局變量中,或者把一組元素直接以參數(shù)形式傳遞給函數(shù),以免造成搜索浪費。
- 合并與放置腳本
在<head>部分的腳本會導(dǎo)致瀏覽器無法并行加載其他文件,因此推介在文檔末尾</body>之前引入script元素,可以讓頁面變得更快;根據(jù)HTTP規(guī)范,瀏覽器每次從同一個域名最多只能同時下載兩個文件,而在下載腳本期間,瀏覽器不會下載其他任何文件,即使是來自不同域名的文件也不會下載,所有其他資源要等腳本加載完畢后才能下載。
- 壓縮腳本
可以使用壓縮工具來刪除腳本文件中不必要的字節(jié),比如空格和注釋,有的壓縮工具設(shè)置會重寫部分代碼,使用更短的變量名,從而減少整體文件大小。精簡后的代碼不易看懂,但會大幅減小文件大小,一般會在壓縮后的文件名后加上.min.,比如 scriptName.min.js 。
第六章 案例:圖片庫改進
ex:
<ul id="imagegallery"><!--平穩(wěn)退化--><li><a href="../imgs/aaa.jpeg">Data1</a></li><li><a href="../imgs/step.png">Data2</a></li><li><a href="../imgs/arrow-right-bold.png">Data3</a></li><li><a href="../imgs/dazongdianpin_logo.png">Data4</a></li> </ul> <img id="placeholder" src="../imgs/CD.jpg" alt="My image gallery"><script>addLoadEvent(prepareGallery);function prepareGallery() {if (!document.getElementById) alert("1");if (!document.getElementsByTagName) alert("2"); //檢查瀏覽器是否支持這個DOM方法if (!document.getElementById("imagegallery")) alert("3"); //即使在網(wǎng)頁上刪除了這個img或者id,js也不會出錯var gallery = document.getElementById("imagegallery");var links = gallery.getElementsByTagName("a");for (var i = 0; i < links.length; i++) {links[i].onclick = function () {return !showpic(this); //由showpic返回值決定是否取消瀏覽器執(zhí)行鏈接被點擊時的默認操作}}}function showpic(whichpic) {if (!document.getElementById("placeholder")) return false;whichpic.getAttribute("href").setAttribute("src", whichpic.getAttribute("href"));return true; //setAttribute成功才會返回true}function addLoadEvent(func) { //將函數(shù)添加到頁面加載時執(zhí)行var oldonload = window.onload;if (typeof window.onload != 'function') {window.onload = func;} else {window.onload = function () {oldonload();func();}}} </script>第七章 動態(tài)創(chuàng)建標(biāo)記
傳統(tǒng)方法
document.write可以方便的把字符串插入文檔(不推介)
<div id="test-div"></div> <script>document.write("<p>This is a <em>content</em> script!;</p>"); </script>innerHTML方法會替換元素內(nèi)的所有內(nèi)容。
<div id="test-div"></div> <script>window.onload = function () {var testdiv = document.getElementById("test-div");testdiv.innerHTML = "<p>This is a <em>content</em> script;</p>"} </script>DOM方法
插入節(jié)點的子元素后
<div id="test-div"></div> <script>var newE = document.createElement("p"); //創(chuàng)建新元素節(jié)點,不可以使用.firstChild.nodeValue賦值,因為創(chuàng)建的標(biāo)簽的nodeValue是nullvar newT = document.createTextNode("hello world~"); //創(chuàng)建新文本節(jié)點newE.appendChild(newT); //把文本節(jié)點插入元素節(jié)點的最后面document.getElementById("test-div").appendChild(newE); //把元素節(jié)點插入原有節(jié)點的最后面 </script>插入元素后:
var place = document.createElement("p"); place.appendChild(document.createTextNode("百度")); var tar = document.getElementById("tar");tar.parentNode.insertBefore(place, tar);插入元素前:
var place = document.createElement("p"); place.appendChild(document.createTextNode("百度")); var tar = document.getElementById("tar");insertAfter(place, hhh);function insertAfter(newElement, targetElement) { //插入目標(biāo)元素后var parent = targetElement.parentNode;if (parent.lastChild === targetElement) {parent.appendChild(newElement);} else {parent.insertBefore(newElement, targetElement.nextElementSibling);} }Ajax
Ajax的主要優(yōu)勢是對頁面的請求以異步的方式發(fā)送到服務(wù)器。而服務(wù)器不會用整個頁面來響應(yīng)請求,它會在后臺處理請求,與此同時用戶還能繼續(xù)瀏覽頁面并與頁面交互腳本則可以按需加載和創(chuàng)建頁面內(nèi)容,而不會打斷用戶的瀏覽體驗。
Ajax的核心是XMLHttpRequest對象,這個對象充當(dāng)瀏覽器中的客戶端與服務(wù)器之間的橋梁角色,以往的請求由瀏覽器發(fā)出,而js通過這個對象可以自己發(fā)送請求,同事也自己處理響應(yīng)。
第八章 充實文檔內(nèi)容
js腳本只應(yīng)該用來充實文檔的內(nèi)容,而避免使用DOM來創(chuàng)建核心內(nèi)容;
遍歷快捷鍵,ex:
總結(jié)
以上是生活随笔為你收集整理的《JavaScript DOM 编程艺术》 读书笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: idea使用总结
- 下一篇: 使用 supervisor 管理进程