第十三章 事件 php
一、事件流:描述的是從頁面中接收事件的順序web
1)事件冒泡:事件開始時由最具體的元素接收,而後逐級向上傳播到較爲不具體的節點面試
2)事件捕獲:事件開始時由不太具體的節點接收,而後逐級向下傳播到最具體的元素正則表達式
3)DOM事件流:經歷三個階段——事件捕獲階段、處於目標階段和事件冒泡階段算法
二、事件處理程序:事件是用戶或瀏覽器自身執行的某種動做,響應某個事件的函數就是事件處理程序chrome
1)HTML事件處理程序;將事件處理程序設置爲 null 就能夠刪除該事件處理程序。數據庫
2)DOM0級事件處理程序:爲元素的事件處理程序屬性設置一個函數;事件處理程序會在其所屬元素的做用域內運行;將事件處理程序設置爲 null 就能夠刪除該事件處理程序。編程
3)DOM2級事件處理程序:addEventListener()和removeEventListener(),都接收三個參數——要處理的事件名、做爲事件處理程序的函數和一個布爾值,布爾值參數若是是true表示在捕獲階段調用事件處理程序,若是是false表示在冒泡階段調用事件處理程序跨域
4)IE事件處理程序(IE和Opera有效):attachEvent()和detachEvent(),都接收兩個參數——事件處理程序名稱與事件處理程序函數;因爲IE及更早的版本只支持事件冒泡,因此經過attachEvent()添加的事件處理程序都會被添加到冒泡階段;能夠爲一個元素添加多個事件處理程序,事件處理程序會在全局做用域中運行,所以this等於window數組
5)跨瀏覽器的事件處理程序:addHandler()用於使用DOM0級方法、DOM2級方法或IE方法來添加事件,removeHandler()用於默認使用DOM0級方法法來移除以前添加的事件,都接收三個參數——要操做的元素、事件名稱和事件處理程序函數;爲了保證處理事件的代碼能在大多數瀏覽器下一致地運行,跨瀏覽器的事件處理程序只處理事件冒泡
三、事件對象:
1)DOM中的事件對象:
兼容DOM的瀏覽器會將一個event對象傳入到事件處理程序中;
preventDefault()用於阻止特定事件的默認行爲,前提是cancelable屬性設置爲true;stopPropagation()用於當即中止事件在DOM層次中的傳播,即取消進一步的事件捕獲或冒泡;
currentTarget屬性代表其事件處理程序當前正在處理事件的那個元素,始終等於this;target屬性代表事件真正的目標;eventPhase屬性代表事件當前正處於事件流的哪一個階段,值爲1代表事件處於捕獲階段,值爲2代表事件處於目標對象上,值爲3代表事件處於冒泡階段;
2)IE中的事件對象:
若是使用DOM0級方法添加事件處理程序時,能夠經過window.event取得event對象;若是使用attachEvent()時,那麼會有一個event對象做爲參數被傳入事件處理程序函數中;若是使用HTML特性添加事件處理程序時,能夠經過一個event變量來訪問event對象;srcElement屬性代表事件真正的目標;returnValue屬性用於阻止特定事件的默認行爲,值爲false代表阻止;cancelBubble屬性用於當即中止事件在DOM層次中的傳播,即取消進一步的事件冒泡,值爲true代表中止;
3)跨瀏覽器的事件對象:getEvent()返回對event對象的引用;getTarget()返回事件的目標,經過檢測event對象的target屬性,若是存在則返回該屬性的值,不然返回srcElement屬性的值;preventDefault()用於取消事件的默認行爲,若是不存在該方法,則設置returnValue的值爲false;stopPropagation()用於阻止事件流,若是不存在該方法,則設置cancelBubble的值爲true;
var EventUtil = {
getEvent: function(event){
return event ? event : window.event;
},
getTarget: function(event){
return event.target || event.srcElement;
},
preventDefault: function(event){
if (event.preventDefault){
event.preventDefault();
} else {
event.returnValue = false;
}
},
stopPropagation: function(event){
if (event.stopPropagation){
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
};
4、事件類型
1)UI事件:指的是那些不必定與用戶操做有關的事件
DOMactive:代表元素已經被用戶操做(經過鼠標或鍵盤)激活;
load:當頁面徹底加載在window上觸發;
unload:當頁面徹底卸載在window上觸發;
abort:當用戶中止下載過程時,若是嵌入的內容沒有加載完,則在<object>元素上觸發;
error:當發生JavaScript錯誤時在window上觸發;
select:當用戶選擇文本框(<input>或<texterea>)中的一或多個字符時觸發;
resize:當窗口或框架大小變化時在window上觸發;
scroll:當用戶滾動帶滾動條的元素中的內容時,在該元素上面觸發;
2)焦點事件:會在頁面元素得到或失去焦點時觸發
blur:在元素失去焦點時觸發(通用);
DOMFocusIn:在元素得到焦點時觸發,冒泡(Opera支持);
DOMFocusOut:在元素失去焦點時觸發(Opera支持);
focus:在元素得到焦點時觸發(通用);
focusin:在元素得到焦點時觸發,冒泡(IE5.5+、Safari5.5+、Opera11.5+和Chrome支持);
focusout:在元素失去焦點時觸發(IE5.5+、Safari5.5+、Opera11.5+和Chrome支持);
3)鼠標和滾輪事件
click:在用戶點擊主鼠標按鈕或者按下回車鍵時觸發;
dblclick:在用戶雙擊主鼠標按鈕時觸發;
mousedown:在用戶按下了任意鼠標按鈕時觸發;
mouseenter:在鼠標光標從元素外部首次移動到元素範圍以內時觸發;
mouseleave:在位於元素上方的鼠標光標移動到元素範圍以外時觸發;
mousemove:當鼠標指針在元素內部移動時重複觸發;
mouseout:在鼠標指針位於一個元素上方,而後用戶將其移入另外一個元素時觸發;
mouseover:在鼠標指針位於一個元素外部,而後用戶將其首次移入另外一個元素邊界以內時觸發;
mouseup:在用戶釋放鼠標按鈕時觸發;
mousewheel:當用戶經過鼠標滾輪在垂直方向上滾動頁面時觸發;當用戶向前滾動頁面時,wheelDelta是120的倍數;當用戶向後滾動頁面時,wheelDelta是-120的倍數
shiftKey、ctrlKey、altKey、metaKey:在用戶按下Shift、Ctrl、Alt和Meta(在Windows鍵盤中是Windows鍵,在蘋果機是Cmd鍵)時布爾值爲true
設置bottom屬性:
var EventUtil = {
getButton: function(event){
if (document.implementation.hasFeature("MouseEvents", "2.0")){
return event.button;
} else {
switch(event.button){
case 0:
case 1:
case 3:
case 5:
case 7:
return 0;
case 2:
case 6:
return 2;
case 4: return 1;
}
}
}
4)鍵盤與文本事件
keydown:當用戶按下鍵盤上的任意鍵時觸發,若是按住不放則會重複觸發;
keypress:當用戶按下鍵盤上的字符鍵時觸發,若是按住不放則會重複觸發;
keyup:當用戶釋放鍵盤的鍵時觸發;
textInput:當用戶將文本插入文本框以前觸發;
5)複合事件
compositionstart:在IME(輸入法編輯器)的文本複合系統打開時觸發,包含正在編輯的文本;
compositionupdate:在想輸入字段中插入新字符時觸發,包含正插入的新字符;
compositionend:在IME的文本複合系統關閉時觸發,包含這次輸入會話中插入的全部字符;
6)變更事件
DOMSubtreeModified:在DOM結構中發生任何變化時觸發;
DOMNodeInserted:在一個節點做爲子節點被插入到另外一個節點中時觸發,在使用appendChild()、replaceChild()和insertBefore()時首先觸發;
DOMNodeRemoved:在節點從其父節點中被移除時觸發,在使用removeChild()和replaceChild()時首先觸發;
DOMNodeInsertedIntoDocument:在一個節點被直接插入文檔或經過子樹間接插入文檔以後觸發;
DOMNodeRemovedFromDocument:在一個節點被直接從文檔中移除或經過子樹間接從文檔中移除以前觸發;
DOMAttrModified:在特性被修改以後觸發;
DOMCharacterDataModified:在文本節點的值發生變化時觸發;
7)HTML5事件
contexmenu事件:用於表示什麼時候應該顯示上下文菜單,以便開發人員取消默認的上下文菜單而提供自定義的菜單;
beforeunload事件:在瀏覽器卸載頁面以前觸發;
DOMContentLoaded:在造成完整的DOM樹以後觸發,無論當時圖像、JavaScript文件、CSS文件或其餘資源是否已經下載完畢;
readystatechange事件:提供與文檔或元素的加載狀態有關的信息,值爲uninitialized(未初始化)、loading(正在加載)、loaded(加載完畢)、interactive(交互)、complete(完成);
pageshow事件:在頁面顯示時觸發,並且是在load事件以後觸發;pagehide事件:在瀏覽器卸載頁面時觸發,並且是在unload事件以前觸發;
hashchange事件:在URL的參數列表(及URL中「#」號後面的全部字符串)發生變化時通知開發人員
8)設備事件
orientationchange事件:當用戶將設備由橫向查看模式切換爲縱向查看模式時觸發,window.orientationchange值爲0(表示肖像模式)、90(表示向左旋轉的橫向模式)、-90(表示向右旋轉的模式);
MozOrientation事件:當設備的加速計檢測到設備方向改變(移動)時觸發,event.x、event.y、event.z的值介於1至-1之間,表示不一樣座標軸上的方向;
deviceorientation事件:當設備的加速計檢測到設備方向改變(朝向)時觸發;
devicemotion事件::當用戶將設備移動時觸發;
9)觸摸與手勢事件
touchstart事件:當手指觸摸屏幕時觸發;
touchmove:當手指在屏幕上滑動時連續觸發;
touchend:當手指從屏幕上移開時觸發;
touchcancel:當系統中止跟蹤觸摸時觸發;
gesturestart:當一個手指已經按在屏幕上而另外一個手指又觸摸屏幕時觸發;
gesturechange:當觸摸屏幕的任何一個手指的位置發生變化時觸發;
gestureend:當任何一個手指從屏幕上面移開時觸發;
五、內存和性能
1)事件委託:利用事件冒泡,只指定一個事件處理程序,就能夠管理某一類型的全部事件
2)移除事件處理程序
六、模擬事件
1)模擬鼠標事件
var btn = document.getElementById("myBtn");
//建立事件對象
var event = document.createEvent("MouseEvents");
//初始化事件對象
event.initMouseEvent("click", true, true, document.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0,null);
//觸發事件
btn.dispatchEvent(event);
2)模擬鍵盤事件
3)模擬其餘事件
4)自定義DOM事件
5)IE中的事件模擬
第十四章 表單腳本
一、表單的基礎知識
1)HTMLFormElement類型的屬性和方法
acceptCharset:服務器可以處理的字符集
action:接收請求的URL,等價於HTML中的action特性;
elements:表單中全部控件的集合;
encype:請求的編碼類型,等價於HTML中的enctype特性;
length:表單中控件的數量;
method:要發送的HTTP請求類型,一般是「get」或「post」,等價於HTML中的method特性;
name:表單的名稱,等價於HTML中的name特性;
reset():將全部表單域重置爲默認值;
submit():提交表單;
target:用於發送請求接收響應的窗口名稱,等價於HTML中的target特性;
2)提交表單
<!-- 通用提交按鈕 -->
<input type=」submit」 value=」Submit Form」>
<!-- 自定義提交按鈕 -->
<bottom type=」submit」 >Submit Form</bottom>
<!-- 圖像按鈕 -->
<input type=」submit」 src=」submit-form.gif」>
3)重置表單
<!-- 通用重置按鈕 -->
<input type=」reset」 value=」Reset Form」>
<!-- 自定義重置按鈕 -->
<bottom type=」reset」 >Reset Form</bottom>
4)表單字段
取得表單字段
var form=document.getElementById(「form1」);
//取得表單中的第一個字段
var field1=form.elements[0];
//取得名爲「textbox1」的字段
var field2=form.elements[「textbox1」];
//取得表單中包含的字段的數量
var fieldCount=form.elements.length;
共有的表單字段屬性(<fieldset>除外)
disable:布爾值,表示當前字段是否被禁用;
form:表示當前字段所屬表單的指針,只讀;
name:當前字段的名稱;
readOnly:布爾值,表示當前字段是否只讀;
tabIndex:表示當前字段的切換(tab)序號;
type:當前字段的類型;
value:當前字段將被提交給服務器的值;
共有的表單字段方法(<fieldset>除外)
focus():用於將瀏覽器的焦點設置到表單字段,使其能夠響應鍵盤事件;
blur():用於從元素中移走焦點;
共有的表單字段事件
blur事件:當前字段失去焦點時觸發;
change事件:對於<input>和<textarea>元素,在它們失去焦點且value值改變時觸發,對於<select>元素,在其選項改變時觸發;
focus事件:當前字段得到焦點時觸發;
二、文本框腳本
1)<input>元素的單行文本框:<input type=」text」 size=」25」 maxlength=」50」 value=」initial value」>
2)<inputarea>元素的多行文本框:<textarea rows=」25」 cols=」5」>initial value</textarea>
3)選擇文本:
select()方法:選擇文本框中的全部文本
select事件
取得選擇的文本:屬性selectionStart和selectionEnd,值爲基於0的數值,表示所選擇文本的範圍(即文本選區開頭和結尾的偏移量)
Function getSelectedText(textbox){
return textbox.value.subString(textbox.selectionStart,textbox.selectionEnd);
}
選擇部分文本:setSelectionRange()方法,接收兩個參數——要選擇的第一個字符的索引和要選擇的最後一個字符以後的字符的索引
4)過濾輸入
屏蔽字符
EventUtil.addHandler(textbox, "keypress", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
var charCode = EventUtil.getCharCode(event);
if (!/\d/.test(String.fromCharCode(charCode)) && charCode > 9 && !event.ctrlKey){
EventUtil.preventDefault(event);
}
});
操做剪切板
beforecopy事件:在發生複製操做前觸發;
copy事件:在發生複製操做時觸發;
beforecut事件:在發生剪切操做前觸發;
cut事件:在發生剪切操做時觸發;
beforepaste事件:在發生粘貼操做前觸發;
paste事件:在發生粘貼操做時觸發;
clipboardData對象:用於訪問剪切板的數據,getData()、setData()和clearData()方法<TextboxClipboardExample01.htm>
var EventUtil = {
getClipboardText: function(event){
var clipboardData = (event.clipboardData || window.clipboardData);
return clipboardData.getData("text");
},
setClipboardText: function(event, value){
if (event.clipboardData){
event.clipboardData.setData("text/plain", value);
} else if (window.clipboardData){
window.clipboardData.setData("text", value);
}
}
};
5)自動切換焦點:<TextboxTabForwardExample01.htm>
function(){
function tabForward(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
if (target.value.length == target.maxLength){
var form = target.form;
for (var i=0, len=form.elements.length; i < len; i++) {
if (form.elements[i] == target) {
if (form.elements[i+1]){
form.elements[i+1].focus();
}
return;
}
}
}
}
6)HTML5約束驗證API
必填字段:required屬性
其餘輸入類型:type=」email」、type=」url」
數值範圍:能夠指定min屬性(最小的可能值)、max屬性(最大的可能性)和step屬性(從min到max的兩個刻度間的差值)
輸入模式:pattern屬性,值爲正則表達式,用於匹配文本框中的值
檢測有效性:checkValidity()方法能夠檢測表單中的某個字段是否有效
禁用驗證:novalidate屬性
三、選擇框腳本
1)HTMLSelectElement類型的屬性和方法
add(newOption,relOption):向控件中插入新<option>元素,其位置在相關項relOption以前;
multiple:布爾值,表示是否容許多項選擇,等價於HTML中的multiple特性;
options:控件中全部<option>元素的HTMLCollection;
remove(index):移除給定位置的選項;
selectedIndex:基於0的選中項的索引,若是沒有選中項,則爲-1;
size:選擇框中可見的行數,等價於HTML中的size特性;
2)HTMLOptionElement對象的屬性
index:當前選項在options集合中的索引;
label:當前選項的標籤,等價於HTML中的label特性;
selected:布爾值,表示當前選項是否被選中;
text:選項的文本;
value:選項的值,等價於HTML中的value特性;
3)選擇選項:第一種方法使用選擇框的selectedIndex屬性,不過只容許選擇一項;第二種方法是將要取得的那一項的selected屬性設置爲true,並且容許動態選擇任意多項;
4)添加選項:
第一種方法是使用DOM方法<SelectboxExample04.htm>
var newOption = document.createElement("option");
newOption.appendChild(document.createTextNode(textTextbox.value));
newOption.setAttribute("value", valueTextbox.value); selectbox.appendChild(newOption);
第二種方法是使用Option構造函數來建立新選項,接收兩個參數——文本和值(可選)
var newOption = new Option(「Option text」,」Option value」);
selectbox.appendChild(newOption);
第三種方法是使用選擇框的add()方法,接收兩個參數——要添加的新選項和將位於新選項以後的選項(可選)
var newOption = new Option(「Option text」,」Option value」);
selectbox.add(newOption,undefined);
5)移除選項
第一種方法是使用DOM方法:selectbox.removeChild(selectbox.options[0]);
第二種方法是使用remove()方法,接收一個參數——要移除選項的索引:selectbox.remove(0);
第三種方法是將相應選項設置爲null:selectbox.option[0]=null;
6)移動和重排選項
將第一個選擇框中的第一個選項移動到第二個選擇框中
var selectbox1 = document.getElementById("selLocations1");
var selectbox2 = document.getElementById("selLocations2");
selectbox2.appendChild(selectbox1.options[0]);
在選擇框中向前移動一個選項的位置
var optionToMove = selectbox.options[1];
selectbox.insertBefore(optionToMove, selectbox.options[optionToMove.index-1]);
四、表單序列化<FormSerializationExample01.htm>
function serialize(form){
var parts = [],
field = null,
i,
en,
j,
optLen,
option,
optValue;
for (i=0, len=form.elements.length; i < len; i++){
field = form.elements[i];
switch(field.type){
case "select-one":
case "select-multiple":
if (field.name.length){
for (j=0, optLen = field.options.length; j < optLen; j++){
option = field.options[j];
if (option.selected){
optValue = "";
if (option.hasAttribute){
optValue = (option.hasAttribute("value") ? option.value : option.text);
} else {
optValue = (option.attributes["value"].specified ? option.value : option.text);
}
parts.push(encodeURIComponent(field.name) + "=" + encodeURIComponent(optValue));
}
}
}
break;
case undefined: //fieldset
case "file": //file input
case "submit": //submit button
case "reset": //reset button
case "button": //custom button
break;
case "radio": //radio button
case "checkbox": //checkbox
if (!field.checked){
break;
}
/* falls through */
default:
//don't include form fields without names
if (field.name.length){
parts.push(encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value));
}
}
}
return parts.join("&");
}
五、富文本編輯
1)使用designMode屬性:首先在頁面中嵌入一個包含空HTML頁面的iframe,其次設置designMode屬性(默認值爲off)爲on時,整個文檔就會變得能夠編輯;
2)使用contenteditable屬性:經過將contenteditable屬性應用給頁面中的任何元素,該元素就能夠當即被編輯;經過設置contenteditate屬性打開或關閉編輯模式,值爲true(打開)、false(關閉)和inherit(從父元素那裏繼承)
3)操做富文本:document.execCommand()用於對文檔執行預約義的命令,接收三個參數——要執行的命令名稱、表示瀏覽器是否應該爲當前命令提供用戶界面的一個布爾值(始終爲false)和執行命令必須一個值(若是不須要值,則傳遞null)
4)富文本選區:使用iframe的getSelection()方法,返回一個表示當前選擇文本的Selection對象
5)表單與富文本<RichTextEditingExample01.htm>
EventUtil.addHandler(form, "submit", function(){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event); target.elements["comments"].value = frames["richedit"].document.body.innerHTML;
});
第十七章 錯誤處理與檢測
一、瀏覽器報告的錯誤
1)IE:IE 是惟一一個在瀏覽器的界面窗體(chrome)中顯示 JavaScript 錯誤信息的瀏覽器。在發生 JavaScript錯誤時,瀏覽器左下角會出現一個黃色的圖標,圖標旁邊則顯示着 "Error on page" (頁面中有錯誤)。打開「Tools」(工具)菜單中的「Internet Options」(Internet 選項)對話框,切換到「Advanced」(高級)選項卡,選中「Display a notification about every script error」(顯示每一個腳本錯誤的通知)複選框。單擊「OK」(肯定)按鈕保存設置。
2)Firefox:默認狀況下,Firefox 在 JavaScript 發生錯誤時不會經過瀏覽器界面給出提示。但它會在後臺將錯誤記錄到錯誤控制檯中。單擊「Tools」(工具)菜單中的「Error Console」(錯誤控制檯)能夠顯示錯誤控制檯。
3)Safari:Windows 和 Mac OS 平臺的 Safari 在默認狀況下都會隱藏所有 JavaScript 錯誤。爲了訪問到這些信息,必須啓用「Develop」(開發)菜單。爲此,須要單擊「Edit」(編輯)菜單中的「Preferences」(偏好設置),而後在「Advanced」(高級)選項卡中,選中「Show develop menu in menubar」(在菜單欄中顯示「開發」菜單)。啓用此項設置以後,就會在 Safari 的菜單欄中看到一個「Develop」菜單。
4)Opera:Opera 在默認狀況下也會隱藏 JavaScript 錯誤,全部錯誤都會被記錄到錯誤控制檯中。要打開錯誤控制檯,須要單擊「Tools」(工具)菜單,在「Advanced」(高級)子菜單項下面再單擊「Error Console」(錯誤控制檯)。
5)Chrome:與 Safari 和 Opera 同樣,Chrome 在默認狀況下也會隱藏 JavaScript 錯誤。全部錯誤都將被記錄到Web Inspector 控制檯中。要查看錯誤消息,必須打開 Web Inspector。爲此,要單擊位於地址欄右側的「Control this page」(控制當前頁)按鈕,選擇「Developer」(開發人員)、「JavaScript console」(JavaScript控制檯)。
二、錯誤處理
1)try-catch語句
try{
// 可能會致使錯誤的代碼
} catch(error){
// 在錯誤發生時怎麼處理
}
finally語句:雖然在 try-catch 語句中是可選的,可是finally 子句一經使用,其代碼不管如何都會執行。只要代碼中包含 finally 子句,則不管 try 或 catch 語句塊中包含什麼代碼——甚至 return 語句,都不會阻止 finally 子句的執行。
function testFinally(){
try {
return 2;
} catch (error){
return 1;
} finally {
return 0;
}
}
2)拋出錯誤:throw操做符,用於隨時拋出自定義操做符。拋出錯誤時,必需要給 throw 操做符指定一個值。
3)error(錯誤)事件:在任何 Web 瀏覽器中, onerror 事件處理程序都不會建立 event 對象,但它能夠接收三個參數:錯誤消息、錯誤所在的 URL 和行號。
4)常見的錯誤類型
類型轉化錯誤:類型轉換錯誤發生在使用某個操做符,或者使用其餘可能會自動轉換值的數據類型的語言結構時,在使用相等(==)和不相等(!=)操做符,或者在 if 、 for 及 while 等流控制語句中使用非布爾值時。
數據類型錯誤:在將預料以外的值傳遞給函數的狀況下,最容易發生數據類型錯誤。
通訊錯誤:第一種通訊錯誤與格式不正確的 URL 或發送的數據有關。最多見的問題是在將數據發送給服務器以前,沒有使用 encodeURIComponent() 對數據進行編碼;另外,在服務器響應的數據不正確時,也會發生通訊錯誤。
5)區分致命錯誤和非致命錯誤:對於非致命錯誤,能夠根據下列一或多個條件來肯定:不影響用戶的主要任務;隻影響頁面的一部分;能夠恢復;重複相同操做能夠消除錯誤。對於致命錯誤,能夠根據下列一或多個條件來肯定:應用程序根本沒法繼續運行;錯誤明顯影響到了用戶的主要操做;會致使其餘連帶錯誤。
6)把錯誤記錄到服務器:要創建這樣一種 JavaScript 錯誤記錄系統,首先須要在服務器上建立一個頁面(或者一個服務器入口點),用於處理錯誤數據。這個頁面的做用無非就是從查詢字符串中取得數據,而後再將數據寫入錯誤日誌中。
三、調試技術
1)將消息記錄到控制檯
2)將消息記錄到當前頁面
3)拋出錯誤
四、常見的IE錯誤
1)操做停止:在修改還沒有加載完成的頁面時,就會發生操做終止錯誤。發生錯誤時,會出現一個模態對話框,告訴你「操做終止。」單擊肯定(OK)按鈕,則卸載整個頁面,繼而顯示一張空白屏幕。要避免這個問題,能夠等到目標元素加載完畢後再對它進行操做,或者使用其餘操做方法。
2)無效字符:所謂無效字符,就是 JavaScript 語法中未定義的字符。在 JavaScript 文件中存在無效字符時,IE 會拋出無效字符(invalid character)錯誤。
3)未找到成員錯誤:IE 中的全部 DOM 對象都是以 COM 對象,而非原生 JavaScript 對象的形式實現的。IE 中的未找到成員(Member not found)錯誤,就是因爲垃圾收集例程配合錯誤所直接致使的。
4)未知運行時錯誤:當使用 innerHTML 或 outerHTML 如下列方式指定 HTML 時,就會發生未知運行時錯誤(Unknown runtime error):一是把塊元素插入到行內元素時,二是訪問表格任意部分( <table> 、 <tbody> 等)的任意屬性時。
5)語法錯誤:只要 IE 一報告發生了語法錯誤(syntax error),緣由多是代碼中少了一個分號,或者花括號先後不對應。若是引用了外部的 JavaScript 文件,而該文件最終並無返回 JavaScript 代碼,IE 也會拋出語法錯誤。
6)系統沒法找到指定資源:在使用 JavaScript請求某個資源 URL,而該 URL的長度超過了 IE對 URL最長不能超過 2083 個字符的限制時,就會發生這個錯誤。IE 不只限制JavaScript 中使用的 URL 的長度,並且也限制用戶在瀏覽器自身中使用的 URL 長度。IE 對 URL路徑還有一個不能超過 2048 個字符的限制。
第二十章 JSON
一、語法
1)簡單值:使用與 JavaScript 相同的語法,能夠在 JSON 中表示字符串、數值、布爾值和 null。但 JSON 不支持 JavaScript 中的特殊值 undefined。JavaScript 字符串與 JSON 字符串的最大區別在於,JSON 字符串必須使用雙引號(單引號會致使語法錯誤)。
2)對象:與 JavaScript 的對象字面量相比,JSON 對象有三個地方不同。首先,沒有聲明變量(JSON 中沒有變量的概念)。其次,沒有末尾的分號(由於這不是 JavaScript 語句,因此不須要分號)。最後,對象的屬性必須加雙引號,屬性的值能夠是c簡單值也能夠是複雜類型值。
3)數組:JSON 數組也沒有變量和分號。把數組和對象結合起來,能夠構成更復雜的數據集合。
二、解析與序列化
1)JSON對象:JSON 對象有兩個方法: stringify() 和 parse() 。在最簡單的狀況下,這兩個方法分別用於把JavaScript 對象序列化爲 JSON 字符串和把 JSON 字符串解析爲原生 JavaScript 值。在序列化 JavaScript 對象時,全部函數及原型成員都會被有意忽略,不體如今結果中。此外,值爲undefined 的任何屬性也都會被跳過。結果中最終都是值爲有效 JSON 數據類型的實例屬性。
2)序列化選項:
JSON.stringify() 還能夠接收另外兩個參數,這兩個參數用於指定以不一樣的方式序列化 JavaScript 對象。第一個參數是個過濾器,能夠是一個數組,也能夠是一個函數;第二個參數是一個選項,表示是否在 JSON 字符串中保留縮進。若是過濾器參數是數組,那麼 JSON.stringify() 的結果中將只包含數組中列出的屬性;若是過濾器參數是函數,傳入的函數接收兩個參數,屬性(鍵)名和屬性值。若是函數返回了undefined ,那麼相應的屬性會被忽略。JSON.stringify() 方法的第三個參數用於控制結果中的縮進和空白符。若是這個參數是一個數值,那它表示的是每一個級別縮進的空格數。
toJSON() 方法用於返回其自身的 JSON 數據格式。假設把一個對象傳入 JSON.stringify() ,序列化該對象的順序以下:
(1) 若是存在 toJSON() 方法並且能經過它取得有效的值,則調用該方法。不然,返回對象自己。
(2) 若是提供了第二個參數,應用這個函數過濾器。傳入函數過濾器的值是第(1)步返回的值。
(3) 對第(2)步返回的每一個值進行相應的序列化。
(4) 若是提供了第三個參數,執行相應的格式化。
3)解析選項:JSON.parse() 方法也能夠接收另外一個參數,該參數是一個函數,將在每一個鍵值對兒上調用。若是還原函數返回 undefined ,則表示要從結果中刪除相應的鍵;若是返回其餘值,則將該值插入到結果中。
第二十一章 Ajax 與 Comet
一、XMLHttpRequest對象
1)建立XMLHttpRequest對象
function createXHR(){
if (typeof XMLHttpRequest != "undefined"){
return new XMLHttpRequest();
} else if (typeof ActiveXObject != "undefined"){
if (typeof arguments.callee.activeXString != "string"){
var versions = [ "MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
"MSXML2.XMLHttp"],
i, len;
for (i=0,len=versions.length; i < len; i++){
try {
new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
break;
} catch (ex){
//跳過
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
} else {
throw new Error("No XHR object available.");
}
}
2)使用XMLHttpRequest對象:
open() 方法接收 3 個參數——要發送的請求的類型( "get" 、 "post" 等)、請求的 URL 和表示是否異步發送請求的布爾值。調用 open() 方法並不會真正發送請求,而只是啓動一個請求以備發送。
send()方法接收一個參數——要做爲請求主體發送的數據。若是不須要經過請求主體發送數據,則必須傳入 null。調用 send() 以後,請求就會被分派到服務器。
abort() 方法用於取消異步請求。
3)HTTP頭部信息
默認狀況下,在發送 XHR 請求的同時,還會發送下列頭部信息。
Accept :瀏覽器可以處理的內容類型。
Accept-Charset :瀏覽器可以顯示的字符集。
Accept-Encoding :瀏覽器可以處理的壓縮編碼。
Accept-Language :瀏覽器當前設置的語言。
Connection :瀏覽器與服務器之間鏈接的類型。
Cookie :當前頁面設置的任何 Cookie。
Host :發出請求的頁面所在的域。
Referer :發出請求的頁面的 URI。
User-Agent :瀏覽器的用戶代理字符串。
setRequestHeader() 方法用於設置自定義的請求頭部信息,接收兩個參數——頭部字段的名稱和頭部字段的值。要成功發送請求頭部信息,必須在調用 open() 方法以後且調用 send() 方法以前調用 setRequestHeader()。
調用 XHR 對象的 getResponseHeader() 方法並傳入頭部字段名稱,能夠取得相應的響應頭部信息。而調用 getAllResponseHeaders() 方法則能夠取得一個包含全部頭部信息的長字符串。
4)GET請求:最經常使用於向服務器查詢某些信息。
5)POST請求:一般用於向服務器發送應該被保存的數據。
二、XMLHttpRequest2級
1)FormData:用於序列化表單以及建立與表單格式相同的數據(用於經過 XHR 傳輸)
2)超時設定:
var xhr = createXHR();
xhr.onreadystatechange = function(){
if (xhr.readyState == 4){
try {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
} catch (ex){
//假設由 ontimeout 事件處理程序處理
}
}
};
xhr.open("get", "timeout.php", true);
xhr.timeout = 1000; // 將超時設置爲 1秒鐘(僅適用於 IE8+ )
xhr.ontimeout = function(){
alert("Request did not return in a second.");
};
xhr.send(null);
3)overrideMimeType() 方法:用於重寫 XHR 響應的 MIME 類型
三、進度事件
1)load事件:響應接收完畢後將觸發 load 事件,所以也就沒有必要去檢查 readyState 屬性了。而 onload 事件處理程序會接收到一個 event 對象,其 target 屬性就指向 XHR 對象實例,於是能夠訪問到 XHR 對象的全部方法和屬性。
var xhr = createXHR();
xhr.onload = function(){
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
};
xhr.open("get", "altevents.php", true);
xhr.send(null);
2)progress事件: onprogress 事件處理程序會接收到一個 event 對象,其 target 屬性是 XHR 對象,但包含着三個額外的屬性: lengthComputable 、 position 和 totalSize 。其中, lengthComputable是一個表示進度信息是否可用的布爾值, position 表示已經接收的字節數, totalSize 表示根據Content-Length 響應頭部肯定的預期字節數。
進度指示器實例:
var xhr = createXHR();
xhr.onprogress = function(event){
var divStatus = document.getElementById("status");
if (event.lengthComputable){
divStatus.innerHTML = "Received " + event.position + " of " +
event.totalSize +" bytes";
}
};
xhr.open("get", "altevents.php", true);
xhr.send(null);
四、跨源資源共享:ORS 背後的基本思想,就是使用自定義的 HTTP 頭部讓瀏覽器與服務器進行溝通,從而決定請求或響應是應該成功,仍是應該失敗。
五、其餘跨域技術
1)圖像Ping:請求的數據是經過查詢字符串形式發送的,而響應能夠是任意內容,但一般是像素圖或 204 響應。經過圖像 Ping,瀏覽器得不到任何具體的數據,但經過偵聽 load 和 error 事件,它能知道響應是何時接收到的。圖像 Ping 最經常使用於跟蹤用戶點擊頁面或動態廣告曝光次數。圖像 Ping 有兩個主要的缺點,一是隻能發送 GET 請求,二是沒法訪問服務器的響應文本。
2)JSONP:JSONP 是被包含在函數調用中的 JSON。JSONP 由兩部分組成——回調函數和數據。回調函數是當響應到來時應該在頁面中調用的函數,回調函數的名字通常是在請求中指定的。而數據就是傳入回調函數中的JSON數據。與圖像 Ping 相比,它的優勢在於可以直接訪問響應文本,支持在瀏覽器與服務器之間雙向通訊。不過,JSONP 也有兩點不足,首先,JSONP 是從其餘域中加載代碼執行,其次,要肯定 JSONP 請求是否失敗並不容易。
3)Comet:Ajax 是一種從頁面向服務器請求數據的技術,而 Comet 則是一種服務器向頁面推送數據的技術。有兩種實現 Comet 的方式:長輪詢和HTTP流。長輪詢是傳統輪詢(也稱爲短輪詢)的一個翻版,即瀏覽器定時向服務器發送請求,看有沒有更新的數據。HTTP流就是瀏覽器向服務器發送一個請求,而服務器保持鏈接打開,而後週期性地向瀏覽器發送數據。
4)服務器發送事件(SSE):是圍繞只讀 Comet 交互推出的 API 或者模式。SSE 支持短輪詢、長輪詢和 HTTP 流,並且能在斷開鏈接時自動肯定什麼時候從新鏈接。
SSE API:用於建立到服務器的單向鏈接,服務器經過這個鏈接能夠發送任意數量的數據。
事件流:服務器事件會經過一個持久的 HTTP 響應發送,這個響應的 MIME 類型爲 text/event-stream 。響應的格式是純文本,最簡單的狀況是每一個數據項都帶有前綴 data:。
5)Web Sockets:Web Sockets的目標是在一個單獨的持久鏈接上提供全雙工、雙向通訊。在 JavaScript 中建立了 Web Socket 以後,會有一個 HTTP 請求發送到瀏覽器以發起鏈接。在取得服務器響應後,創建的鏈接會使用 HTTP 升級從 HTTP 協議交換爲 Web Socket 協議。
六、安全
1)要求以 SSL 鏈接來訪問能夠經過 XHR 請求的資源。
2)要求每一次請求都要附帶通過相應算法計算獲得的驗證碼。
請注意,下列措施對防範 CSRF 攻擊不起做用。
3)要求發送 POST 而不是 GET 請求——很容易改變。
4)檢查來源 URL 以肯定是否可信——來源記錄很容易僞造。
5)基於 cookie 信息進行驗證——一樣很容易僞造。
第二十二章 高級技巧
一、高級函數
1)安全類型檢測
function isFunction(value){
return Object.prototype.toString.call(value) == "[object Function]";
}
2)做用域安全的構造函數:做用域安全的構造函數在進行任何更改前,首先確認 this 對象是正確類型的實例。若是不是,那麼會建立新的實例並返回。
3)惰性載入函數:惰性載入表示函數執行的分支僅會發生一次。有兩種實現惰性載入的方式,第一種就是在函數被調用時再處理函數。在第一次調用的過程當中,該函數會被覆蓋爲另一個按合適方式執行的函數,這樣任何對原函數的調用都不用再通過執行的分支了。第二種實現惰性載入的方式是在聲明函數時就指定適當的函數。這樣,第一次調用函數時就不會損失性能了,而在代碼首次加載時會損失一點性能。
4)函數綁定:函數綁定要建立一個函數,能夠在特定的 this 環境中以指定參數調用另外一個函數。該技巧經常和回調函數與事件處理程序一塊兒使用,以便在將函數做爲變量傳遞的同時保留代碼執行環境。
5)函數柯里化:用於建立已經設置好了一個或多個參數的函數。函數柯里化的基本方法和函數綁定是同樣的:使用一個閉包返回一個函數。二者的區別在於,當函數被調用時,返回的函數還須要設置一些傳入的參數。
二、防篡改對象:一旦把對象定義爲防篡改,就沒法撤銷了。
1)不可擴展對象:在調用了 Object.preventExtensions() 方法後,就不能給對象添加新屬性和方法了。在非嚴格模式下,給對象添加新成員會致使靜默失敗。
2)密封的對象:密封對象不可擴展,並且已有成員的 [[Configurable]] 特性將被設置爲 false ,這就意味着不能刪除屬性和方法,由於不能使用 Object.defineProperty() 把數據屬性修改成訪問器屬性,或者相反。屬性值是能夠修改的。使用 Object.isSealed() 方法能夠肯定對象是否被密封了。由於被密封的對象不可擴展,因此用Object.isExtensible() 檢測密封的對象也會返回 false。
3)凍結的對象:凍結的對象既不可擴展,又是密封的,並且對象數據屬性的 [[Writable]] 特性會被設置爲 false 。若是定義 [[Set]] 函數,訪問器屬性仍然是可寫的。 Object.freeze() 方法能夠用來凍結對象。由於凍結對象既是密封的又是不可擴展的,因此用 Object.isExtensible() 和 Object.isSealed() 檢測凍結對象將分別返回 false和 true。
三、高級定時器: setTimeout() 和 setInterval(),window.setTimeout(function(){Time();setTimeout(arguments.callee, 1000);}, 1000);
1)Yielding Processes:chunk() 方法接受三個參數:要處理的項目的數組,用於處理項目的函數,以及可選的運行該函數的環境。
function chunk(array, process, context){
setTimeout(function(){
var item = array.shift();
process.call(context, item);
if (array.length > 0){
setTimeout(arguments.callee, 100);
}
}, 100);
}
2)函數節流:基本思想是指,某些代碼不能夠在沒有間斷的狀況連續重複執行。第一次調用函數,建立一個定時器,在指定的時間間隔以後運行代碼。當第二次調用該函數時,它會清除前一次的定時器並設置另外一個。若是前一個定時器已經執行過了,這個操做就沒有任何意義。然而,若是前一個定時器還沒有執行,其實就是將其替換爲一個新的定時器。目的是隻有在執行函數的請求中止了一段時間以後才執行。
function throttle(method, context) {
clearTimeout(method.tId);
method.tId= setTimeout(function(){
method.call(context);
}, 100);
}
四、自定義事件
function EventTarget(){
this.handlers = {};
}
EventTarget.prototype = {
constructor: EventTarget,
addHandler: function(type, handler){
if (typeof this.handlers[type] == "undefined"){
this.handlers[type] = [];
}
this.handlers[type].push(handler);
},
fire: function(event){
if (!event.target){
event.target = this;
}
if (this.handlers[event.type] instanceof Array){
var handlers = this.handlers[event.type];
for (var i=0, len=handlers.length; i < len; i++){
handlers[i](event);
}
}
},
removeHandler: function(type, handler){
if (this.handlers[type] instanceof Array){
var handlers = this.handlers[type];
for (var i=0, len=handlers.length; i < len; i++){
if (handlers[i] === handler){
break;
}
}
handlers.splice(i, 1);
}
}
};
五、拖放
var DragDrop = function(){
var dragging = null;
diffX = 0;
diffY = 0;
function handleEvent(event){
//獲取事件和目標
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
//肯定事件類型
switch(event.type){
case "mousedown":
if (target.className.indexOf("draggable") > -1){
dragging = target;
diffX = event.clientX - target.offsetLeft;
diffY = event.clientY - target.offsetTop;
}
break;
case "mousemove":
if (dragging !== null){
//指定位置
dragging.style.left = (event.clientX - diffX) + "px";
dragging.style.top = (event.clientY - diffY) + "px";
}
break;
case "mouseup":
dragging = null;
break;
}
};
//公共接口
return {
enable: function(){
EventUtil.addHandler(document, "mousedown", handleEvent);
EventUtil.addHandler(document, "mousemove", handleEvent);
EventUtil.addHandler(document, "mouseup", handleEvent);
},
disable: function(){
EventUtil.removeHandler(document, "mousedown", handleEvent);
EventUtil.removeHandler(document, "mousemove", handleEvent);
EventUtil.removeHandler(document, "mouseup", handleEvent);
}
}
}();
第二十三章 離線應用與客戶端存儲
一、離線檢測: navigator.onLine屬性,這個屬性值爲 true 表示設備能上網,值爲 false 表示設備離線。事件online 和 offline ,當網絡從離線變爲在線或者從在線變爲離線時,分別觸發這兩個事件,這兩個事件在 window 對象上觸發。
二、應用緩存
三、數據存儲
1)Cookie:最初是在客戶端用於存儲會話信息的。該標準要求服務器對任意 HTTP 請求發送 Set-Cookie HTTP 頭做爲響應的一部分,其中包含會話信息。經過爲每一個請求添加 Cookie HTTP 頭將信息發送回服務器,發送回服務器的額外信息能夠用於惟一驗證客戶來自於發送的哪一個請求。
2)JavaScript中的cookie:當用來獲取屬性值時,document.cookie 返回當前頁面可用的(根據 cookie 的域、路徑、失效時間和安全設置)全部 cookie的字符串,一系列由分號隔開的名值對兒。基本的cookie 操做有三種:讀取、寫入和刪除。
var CookieUtil = {
get: function (name){
var cookieName = encodeURIComponent(name) + "=",
cookieStart = document.cookie.indexOf(cookieName),
cookieValue = null;
if (cookieStart > -1){
var cookieEnd = document.cookie.indexOf(";", cookieStart);
if (cookieEnd == -1){
cookieEnd = document.cookie.length;
}
cookieValue=decodeURIComponent(document.cookie. substring(cookieStart+ cookieName.length, cookieEnd));
}
return cookieValue;
},
set: function (name, value, expires, path, domain, secure) {
var cookieText = encodeURIComponent(name) + "=" +
encodeURIComponent(value);
if (expires instanceof Date) {
cookieText += "; expires=" + expires.toGMTString();
}
if (path) {
cookieText += "; path=" + path;
}
if (domain) {
cookieText += "; domain=" + domain;
}
if (secure) {
cookieText += "; secure";
}
document.cookie = cookieText;
},
unset: function (name, path, domain, secure){
this.set(name, "", new Date(0), path, domain, secure);
}
};
3)IE用戶數據:用戶數據容許每一個文檔最多128KB 數據,每一個域名最多 1MB 數據。要使用持久化用戶數據,首先必須以下所示,使用 CSS 在某個元素上指定 userData 行爲:
<div style="behavior:url(#default#userData)" id="dataStore"></div>
4)Web存儲機制:Web Storage 的目的是克服由 cookie 帶來的一些限制,當數據須要被嚴格控制在客戶端上時,無須持續地將數據發回服務器。Web Storage 的兩個主要目標是:提供一種在 cookie 以外存儲會話數據的途徑;提供一種存儲大量能夠跨會話存在的數據的機制。
5)IndexedDB:IndexedDB 的思想是建立一套 API,方便保存和讀取 JavaScript 對象,同時還支持查詢及搜索。
IndexedDB大多數操做會以請求方式異步進行,但這些操做會在後期執行,而後若是成功則返回結果,若是失敗則返回錯誤。
數據庫:IndexedDB最大的特點是使用對象保存數據,而不是使用表來保存數據。一個 IndexedDB 數據庫,就是一組位於相同命名空間下的對象的集合。
對象存儲空間:若是數據庫的版本與你傳入的版本不匹配,那可能就須要建立一個新的對象存儲空間。
事務:在數據庫對象上調用 transaction() 方法能夠建立事務。任什麼時候候,只要想讀取或修改數據,都要經過事務來組織全部操做。
使用遊標查詢:使用事務能夠直接經過已知的鍵檢索單個對象。而在須要檢索多個對象的狀況下,則須要在事務內部建立遊標。遊標就是一指向結果集的指針。與傳統數據庫查詢不一樣,遊標並不提早收集結果。遊標指針會先指向結果中的第一項,在接到查找下一項的指令時,纔會指向下一項。
鍵範圍:鍵範圍爲使用遊標增添了一些靈活性。鍵範圍由 IDBKeyRange 的實例表示。
設定遊標方向:
索引:
併發問題:若是瀏覽器的兩個不一樣的標籤頁打開了同一個頁面,那麼一個頁面試圖更新另外一個頁面還沒有準備就緒的數據庫,問題就有可能發生。只有當瀏覽器中僅有一個標籤頁使用數據庫的狀況下,調用 setVersion() 才能完成操做。
限制:首先,IndexedDB 數據庫只能由同源(相同協議、域名和端口)頁面操做,所以不能跨域共享信息。其次,每一個來源的數據庫佔用的磁盤空間也有限制。
第二十四章 最佳實踐
一、可維護性
1)可維護性代碼:
可理解性——其餘人能夠接手代碼並理解它的意圖和通常途徑,而無需原開發人員的完整解釋。
q 直觀性——代碼中的東西一看就能明白,無論其操做過程多麼複雜。
q 可適應性——代碼以一種數據上的變化不要求徹底重寫的方法撰寫。
q 可擴展性——在代碼架構上已考慮到在將來容許對核心功能進行擴展。
2)代碼約定
可讀性:首先可讀性與代碼做爲文本文件的格式化方式有關,其次是註釋。
變量和函數命名:變量名應爲名詞; 函數名應該以動詞開始,返回布爾類型值的函數通常以 is 開頭;變量和函數都應使用合乎邏輯的名字,不要擔憂長度。長度問題能夠經過後處理和壓縮來緩解。
變量類型透明:第一種方式是初始化。第二種方法是使用匈牙利標記法來指定變量類型, "o" 表明對象, "s" 表明字符串, "i"表明整數, "f" 表明浮點數, "b" 表明布爾型。最後一種指定變量類型的方式是使用類型註釋。
3)鬆散耦合
解耦 HTML/JavaScript:HTML 是數據,JavaScript 是行爲。理想狀況是,HTML 和 JavaScript 應該徹底分離,並經過外部文件和使用 DOM 附加行爲來包含 JavaScript。
解耦 CSS/JavaScript:經過只修改某個元素的 CSS 類,就可讓大部分樣式信息嚴格保留在 CSS 中。JavaScript 能夠更改樣式類,但並不會直接影響到元素的樣式。
解耦應用邏輯/事件處理程序:勿將 event 對象傳給其餘方法;只傳來自 event 對象中所需的數據;任何能夠在應用層面的動做都應該能夠在不執行任何事件處理程序的狀況下進行;任何事件處理程序都應該處理事件,而後將處理轉交給應用邏輯。
4)編程實踐
尊重對象全部權:不要爲實例或原型添加屬性;不要爲實例或原型添加方法;不要重定義已存在的方法。
避免全局量
避免與null進行比較: 若是值應爲一個引用類型,使用 instanceof 操做符檢查其構造函數;若是值應爲一個基本類型,使用 typeof 檢查其類型;若是是但願對象包含某個特定的方法名,則使用 typeof 操做符確保指定名字的方法存在於對象上。
使用常量:重複值;用戶界面字符串;URLs;任意可能會更改的值
二、性能
1)注意做用域:避免全局查找;避免 with 語句
2)選擇正確方法:避免沒必要要的屬性查找;優化循環——減值迭代、簡化終止條件、簡化循環體、使用後測試循環;展開循環;避免雙重解釋;原生方法較快; Switch 語句較快; 位運算符較快
3)最小化語句數
多個變量聲明:在 JavaScript 中全部的變量均可以使用單個 var 語句來聲明。
插入迭代值:當使用迭代值(也就是在不一樣的位置進行增長或減小的值)的時候,儘量合併語句。
使用數組和對象字面量
4)優化DOM交互
最小化現場更新:第一種是將列表從頁面上移除,最後進行更新,最後再將列表插回到一樣的位置。第二個方法是使用文檔片斷來構建 DOM 結構,接着將其添加到 List 元素中。
使用innerHTML
使用事件代理
注意 HTMLCollection
第二十五章 新興的API
一、requestAnimationFrame():
1)mozRequestAnimationFrame() :經過mozRequestAnimationFrame() 告訴瀏覽器某些 JavaScript 代碼將要執行動畫,接收一個參數——即在重繪屏幕前調用的一個函數,這個函數用於改變下一次重繪時的 DOM樣式;接收一個參數——時間碼(從1970年1月1日起至今的毫秒數),表示下一次重繪的實際發生時間。
2)webkitRequestAnimationFrame 與 msRequestAnimationFrame:這兩個版本與 Mozilla 的版本有兩個方面的微小差別。首先,不會給回調函數傳遞時間碼,所以你沒法知道下一次重繪將發生在什麼時間。其次,Chrome 又增長了第二個可選的參數,即將要發生變化的 DOM 元素。知道了重繪將發生在頁面中哪一個特定元素的區域內,就能夠將重繪限定在該區域中。
二、Page Visibility API:用於讓開發人員知道頁面是否對用戶可見
document.hidden :表示頁面是否隱藏的布爾值。頁面隱藏包括頁面在後臺標籤頁中或者瀏覽器最小化。
document.visibilityState :表示下列 4 個可能狀態的值。
n 頁面在後臺標籤頁中或瀏覽器最小化。
n 頁面在前臺標籤頁中。
n 實際的頁面已經隱藏,但用戶能夠看到頁面的預覽(就像在 Windows 7 中,用戶把鼠標移動到任務欄的圖標上,就能夠顯示瀏覽器中當前頁面的預覽)。
n 頁面在屏幕外執行預渲染處理。
visibilitychange 事件:當文檔從可見變爲不可見或從不可見變爲可見時,觸發該事件。
三、Geolocation API:用於訪問到用戶的當前位置信息。
四、File API:用於在客戶端訪問用戶計算機中的文件,並更好地對這些文件執行操做。
五、Web Timing API:用於讓開發人員經過 JavaScript 就能使用瀏覽器內部的度量結果,經過直接讀取這些信息能夠作任何想作的分析。
六、Web Workers:解決JavaScript 進程會致使瀏覽器凍結用戶界面的問題。