web前端筆試面試總結_第1頁
web前端筆試面試總結_第2頁
web前端筆試面試總結_第3頁
web前端筆試面試總結_第4頁
web前端筆試面試總結_第5頁
已閱讀5頁,還剩51頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

前端是龐大的,包括HTML、CSS、Javascript、Image、Flash等等各種各樣的資源。前端優化是復雜的,針對方方面面的資源都有不同的方式。那么,前端優化的目的是什么?1.從用戶角度而言,優化能夠讓頁面加載得更快、對用戶的操作響應得更及時,能夠給用戶提供更為友好的體驗。2.從服務商角度而言,優化能夠減少頁面請求數、或者減小請求所占帶寬,能夠節省可觀的資源??傊‘數膬灮粌H能夠改善站點的用戶體驗并且能夠節省相當的資源利用。前端優化的途徑有很多,按粒度大致可以分為兩類,第一類是頁面級別的優化,例如HTTP請求數、腳本的無阻塞加載、內聯腳本的位置優化等;第二類則是代碼級別的優化,例如Javascript中的DOM操作優化、CSS選擇符優化、圖片優化以及HTML結構優化等等。另外,本著提高投入產出比的目的,后文提到的各種優化策略大致按照投入產出比從大到小的順序排列。一、頁面級優化1.減少HTTP請求數這條策略基本上所有前端人都知道,而且也是最重要最有效的。都說要減少HTTP請求,那請求多了到底會怎么樣呢?首先,每個請求都是有成本的,既包含時間成本也包含資源成本。一個完整的請求都需要經過DNS尋址、與服務器建立連接、發送數據、等待服務器響應、接收數據這樣一個“漫長”而復雜的過程。時間成本就是用戶需要看到或者“感受”到這個資源是必須要等待這個過程結束的,資源上由于每個請求都需要攜帶數據,因此每個請求都需要占用帶寬。另外,由于瀏覽器進行并發請求的請求數是有上限的(具體參見此處),因此請求數多了以后,瀏覽器需要分批進行請求,因此會增加用戶的等待時間,會給用戶造成站點速度慢這樣一個印象,即使可能用戶能看到的第一屏的資源都已經請求完了,但是瀏覽器的進度條會一直存在。減少HTTP請求數的主要途徑包括:(1).從設計實現層面簡化頁面如果你的頁面像百度首頁一樣簡單,那么接下來的規則基本上都用不著了。保持頁面簡潔、減少資源的使用時最直接的。如果不是這樣,你的頁面需要華麗的皮膚,則繼續閱讀下面的內容。(2).合理設置HTTP緩存緩存的力量是強大的,恰當的緩存設置可以大大的減少HTTP請求。以有啊首頁為例,當瀏覽器沒有緩存的時候訪問一共會發出78個請求,共600多K數據(如圖1.1),而當第二次訪問即瀏覽器已緩存之后訪問則僅有10個請求,共20多K數據(如圖1.2)。(這里需要說明的是,如果直接F5刷新頁面的話效果是不一樣的,這種情況下請求數還是一樣,不過被緩存資源的請求服務器是304響應,只有Header沒有Body,可以節省帶寬)怎樣才算合理設置?原則很簡單,能緩存越多越好,能緩存越久越好。例如,很少變化的圖片資源可以直接通過HTTPHeader中的Expires設置一個很長的過期頭;變化不頻繁而又可能會變的資源可以使用Last-Modifed來做請求驗證。盡可能的讓資源能夠在緩存中待得更久。關于HTTP緩存的具體設置和原理此處就不再詳述了,有興趣的可以參考下列文章:HTTP1.1協議中關于緩存策略的描述FiddlerHTTPPerformance中關于緩存的介紹(3).資源合并與壓縮如果可以的話,盡可能的將外部的腳本、樣式進行合并,多個合為一個。另外,CSS、Javascript、Image都可以用相應的工具進行壓縮,壓縮后往往能省下不少空間。(4).CSSSprites合并CSS圖片,減少請求數的又一個好辦法。(5).InlineImages使用data:URLscheme的方式將圖片嵌入到頁面或CSS中,如果不考慮資源管理上的問題的話,不失為一個好辦法。如果是嵌入頁面的話換來的是增大了頁面的體積,而且無法利用瀏覽器緩存。使用在CSS中的圖片則更為理想一些。(6).LazyLoadImages這條策略實際上并不一定能減少HTTP請求數,但是卻能在某些條件下或者頁面剛加載時減少HTTP請求數。對于圖片而言,在頁面剛加載的時候可以只加載第一屏,當用戶繼續往后滾屏的時候才加載后續的圖片。這樣一來,假如用戶只對第一屏的內容感興趣時,那剩余的圖片請求就都節省了。有啊首頁曾經的做法是在加載的時候把第一屏之后的圖片地址緩存在Textarea標簽中,待用戶往下滾屏的時候才“惰性”加載。2.將外部腳本置底前文有談到,瀏覽器是可以并發請求的,這一特點使得其能夠更快的加載資源,然而外鏈腳本在加載時卻會阻塞其他資源,例如在腳本加載完成之前,它后面的圖片、樣式以及其他腳本都處于阻塞狀態,直到腳本加載完成后才會開始加載。如果將腳本放在比較靠前的位置,則會影響整個頁面的加載速度從而影響用戶體驗。解決這一問題的方法有很多,在這里有比較詳細的介紹(這里是譯文和更詳細的例子),而最簡單可依賴的方法就是將腳本盡可能的往后挪,減少對并發下載的影響。3.異步執行inline腳本inline腳本對性能的影響與外部腳本相比,是有過之而無不及。首頁,與外部腳本一樣,inline腳本在執行的時候一樣會阻塞并發請求,除此之外,由于瀏覽器在頁面處理方面是單線程的,當inline腳本在頁面渲染之前執行時,頁面的渲染工作則會被推遲。簡而言之,inline腳本在執行的時候,頁面處于空白狀態。鑒于以上兩點原因,建議將執行時間較長的inline腳本異步執行,異步的方式有很多種,例如使用script元素的defer屬性(存在兼容性問題和其他一些問題,例如不能使用document.write)、使用setTimeout,此外,在HTML5中引入了WebWorkers的機制,恰恰可以解決此類問題。4.LazyLoadJavascript隨著Javascript框架的流行,越來越多的站點也使用起了框架。不過,一個框架往往包括了很多的功能實現,這些功能并不是每一個頁面都需要的,如果下載了不需要的腳本則算得上是一種資源浪費-既浪費了帶寬又浪費了執行花費的時間。目前的做法大概有兩種,一種是為那些流量特別大的頁面專門定制一個專用的mini版框架,另一種則是LazyLoad。YUI則使用了第二種方式,在YUI的實現中,最初只加載核心模塊,其他模塊可以等到需要使用的時候才加載。5.將CSS放在HEAD中如果將CSS放在其他地方比如BODY中,則瀏覽器有可能還未下載和解析到CSS就已經開始渲染頁面了,這就導致頁面由無CSS狀態跳轉到CSS狀態,用戶體驗比較糟糕。除此之外,有些瀏覽器會在CSS下載完成后才開始渲染頁面,如果CSS放在靠下的位置則會導致瀏覽器將渲染時間推遲。6.異步請求Callback在某些頁面中可能存在這樣一種需求,需要使用script標簽來異步的請求數據。類似:Javascript:/*Callback函數*/

functionmyCallback(info){

//dosomethinghere

}

HTML:<scripttype="text/javascript"src="/cb"></script>cb返回的內容:myCallback('Helloworld!');

像以上這種方式直接在頁面上寫<script>對頁面的性能也是有影響的,即增加了頁面首次加載的負擔,推遲了DOMLoaded和window.onload事件的觸發時機。如果時效性允許的話,可以考慮在DOMLoaded事件觸發的時候加載,或者使用setTimeout方式來靈活的控制加載的時機。7.減少不必要的HTTP跳轉對于以目錄形式訪問的HTTP鏈接,很多人都會忽略鏈接最后是否帶’/',假如你的服務器對此是區別對待的話,那么你也需要注意,這其中很可能隱藏了301跳轉,增加了多余請求。具體參見下圖,其中第一個鏈接是以無’/'結尾的方式訪問的,于是服務器有了一次跳轉。8.避免重復的資源請求這種情況主要是由于疏忽或頁面由多個模塊拼接而成,然后每個模塊中請求了同樣的資源時,會導致資源的重復請求二、代碼級優化1.Javascript(1).DOMDOM操作應該是腳本中最耗性能的一類操作,例如增加、修改、刪除DOM元素或者對DOM集合進行操作。如果腳本中包含了大量的DOM操作則需要注意以下幾點:a.HTMLCollection在腳本中document.images、document.forms、getElementsByTagName()返回的都是HTMLCollection類型的集合,在平時使用的時候大多將它作為數組來使用,因為它有length屬性,也可以使用索引訪問每一個元素。不過在訪問性能上則比數組要差很多,原因是這個集合并不是一個靜態的結果,它表示的僅僅是一個特定的查詢,每次訪問該集合時都會重新執行這個查詢從而更新查詢結果。所謂的“訪問集合”包括讀取集合的length屬性、訪問集合中的元素。因此,當你需要遍歷HTMLCollection的時候,盡量將它轉為數組后再訪問,以提高性能。即使不轉換為數組,也請盡可能少的訪問它,例如在遍歷的時候可以將length屬性、成員保存到局部變量后再使用局部變量。b.Reflow&Repaint除了上面一點之外,DOM操作還需要考慮瀏覽器的Reflow和Repaint,因為這些都是需要消耗資源的,具體的可以參加以下文章:如何減少瀏覽器的repaint和reflow?UnderstandingInternetExplorerRenderingBehaviourNotesonHTMLReflow(2).慎用with

with(obj){p=1};代碼塊的行為實際上是修改了代碼塊中的執行環境,將obj放在了其作用域鏈的最前端,在with代碼塊中訪問非局部變量是都是先從obj上開始查找,如果沒有再依次按作用域鏈向上查找,因此使用with相當于增加了作用域鏈長度。而每次查找作用域鏈都是要消耗時間的,過長的作用域鏈會導致查找性能下降。因此,除非你能肯定在with代碼中只訪問obj中的屬性,否則慎用with,替代的可以使用局部變量緩存需要訪問的屬性。(3).避免使用eval和Function每次eval或Function構造函數作用于字符串表示的源代碼時,腳本引擎都需要將源代碼轉換成可執行代碼。這是很消耗資源的操作——通常比簡單的函數調用慢100倍以上。eval函數效率特別低,由于事先無法知曉傳給eval的字符串中的內容,eval在其上下文中解釋要處理的代碼,也就是說編譯器無法優化上下文,因此只能有瀏覽器在運行時解釋代碼。這對性能影響很大。Function構造函數比eval略好,因為使用此代碼不會影響周圍代碼;但其速度仍很慢。此外,使用eval和Function也不利于Javascript壓縮工具執行壓縮。(4).減少作用域鏈查找前文談到了作用域鏈查找問題,這一點在循環中是尤其需要注意的問題。如果在循環中需要訪問非本作用域下的變量時請在遍歷之前用局部變量緩存該變量,并在遍歷結束后再重寫那個變量,這一點對全局變量尤其重要,因為全局變量處于作用域鏈的最頂端,訪問時的查找次數是最多的。低效率的寫法://全局變量

varglobalVar=1;

functionmyCallback(info){

for(vari=100000;i--;){

//每次訪問globalVar都需要查找到作用域鏈最頂端,本例中需要訪問100000次

globalVar+=i;

}

}

更高效的寫法://全局變量

varglobalVar=1;

functionmyCallback(info){

//局部變量緩存全局變量

varlocalVar=globalVar;

for(vari=100000;i--;){

//訪問局部變量是最快的

localVar+=i;

}

//本例中只需要訪問2次全局變量

globalVar=localVar;

}此外,要減少作用域鏈查找還應該減少閉包的使用。(5).數據訪問Javascript中的數據訪問包括直接量(字符串、正則表達式)、變量、對象屬性以及數組,其中對直接量和局部變量的訪問是最快的,對對象屬性以及數組的訪問需要更大的開銷。當出現以下情況時,建議將數據放入局部變量:a.對任何對象屬性的訪問超過1次b.對任何數組成員的訪問次數超過1次另外,還應當盡可能的減少對對象以及數組深度查找。(6).字符串拼接在Javascript中使用"+"號來拼接字符串效率是比較低的,因為每次運行都會開辟新的內存并生成新的字符串變量,然后將拼接結果賦值給新變量。與之相比更為高效的做法是使用數組的join方法,即將需要拼接的字符串放在數組中最后調用其join方法得到結果。不過由于使用數組也有一定的開銷,因此當需要拼接的字符串較多的時候可以考慮用此方法。關于Javascript優化的更詳細介紹請參考:WriteEfficientJavascript(PPT)EfficientJavaScript2.CSS選擇符在大多數人的觀念中,都覺得瀏覽器對CSS選擇符的解析式從左往右進行的,例如#tocA{color:#444;}這樣一個選擇符,如果是從右往左解析則效率會很高,因為第一個ID選擇基本上就把查找的范圍限定了,但實際上瀏覽器對選擇符的解析是從右往左進行的。如上面的選擇符,瀏覽器必須遍歷查找每一個A標簽的祖先節點,效率并不像之前想象的那樣高。根據瀏覽器的這一行為特點,在寫選擇符的時候需要注意很多事項,有人已經一一列舉了,詳情參考此處。3.HTML對HTML本身的優化現如今也越來越多的受人關注了,詳情可以參見這篇總結性文章。4.Image壓縮圖片壓縮是個技術活,不過現如今這方面的工具也非常多,壓縮之后往往能帶來不錯的效果,具體的壓縮原理以及方法在《EvenFasterWebSites》第10章有很詳細的介紹,有興趣的可以去看看??偨Y本文從頁面級以及代碼級兩個粒度對前端優化的各種方式做了一個總結,這些方法基本上都是前端開發人員在開發的過程中可以借鑒和實踐的,除此之外,完整的前端優化還應該包括很多其他的途徑,例如CDN、Gzip、多域名、無Cookie服務器等等,由于對于開發人員的可操作性并不強大,在此也就不多敘述了,詳細的可以參考Yahoo和Google的這些“金科玉律”。1.Javascript簡介HTML是純靜態的的頁面,而Javascript讓頁面有了動態的效果,比如;OA中模塊的拖拉所有的瀏覽器都會內置Javascript的解釋器1992年Nombas公司開發出C減減的嵌入式腳本語言。這是最好的HTML頁面的腳本語言。Netscape為了擴展其瀏覽器的功能,開發了一套LiveScript,并與1995年與SUN公司聯合把其改名為javascript,它的主要目的是處理一些輸入的有效性驗證,而之前這個工作是留給perl之類的服務器端語言完成,在以前使用電話線調制解調器(28.8kb/s)的時代,如此慢的與服務器交互,這絕對是一件很痛苦的事情。Javascript的出現,解決了這個問題,因為它的驗證是基于客戶端的。微軟公司早期版本的瀏覽器僅支持自己的vbscript,但后來不得不加入javascriptIE3中搭載Javascipt的克隆版本,命名為jscript在一次技術會議中,sun,microsoft,netscape公司聯合制定了ECMA-Script標準在2005前,網頁上提示框,廣告越來越多,把javascipt濫用,使javascript背上了大量的罪名。2005年,google公司的網上產品(google地圖,gmail,google搜索建議)等使得ajax興起,而javascript便是ajax最重要的元素之一Javascript有三個部分組成ECMAScriptDOMBOMWEB標準網頁主要有三部分組成(結構HTML,XHTML,表現CSS,行為DOM,ECMA)2.ECMA腳本Javascript的語法區分大小寫弱類型變量varage=10varname=”dd”每行結尾的分號可有可無,但建議還是加上注釋與java相同變量變量是通過var關鍵字來聲明的。(Variable)變量的命名規則與java一致注釋有三種:///**/<!---->這個只能注釋單行2.1javascript的Helloworlddocument.write()是寫在文檔的最前面2.2slice()、substring()、subtrSlice和substring(2,5)指的是從第3為開始,?。?-2)=3個數,其中slice的參數可以為負Substr(2,5)指的是從第3為開始,取5個數。但ECMAscript沒有對該方法進行標準化,因此盡量少使用該方法2.3indexOf()和lastIndexOf(),isNan,typeOfindexOf(”i”)//從前往后,i在第幾位indexOf(”i”,3)可選參數,從第幾個字符開始往后找lastIndexOf(”i”)//從后往前,i在第幾位lastIndexOf(”i”,3)//從后往前,i在第幾位如果沒找到,則返回-1String類型的變量,在Java中,用“”符號表示字符串,用’’表示單個字符。而在javascript中這兩種都可以Nan(notanumber)Alert(nan==nan)返回false,因此不推薦使用nan本身,推薦函數isNanAlert(isNanN(“ab”));//返回falsetypeof運算符varstmp=“test”;alert(typeofstmp);//輸出stringalert(typeof1);//輸出number此外:還有boolean,undefined,object(如果是引用類型或者null值,null值返回object,這其實是ecmascript的一個錯誤)當聲明的變量未初始化的時候,它的值就是undefined.當沒有這個變量的時候,typeof變返回的值也是undefined。但是沒聲明的變量是不能參與計算的。當函數無明確返回值時,返回的也是undefinedFunctiona(){}Alert(a()==undefined)//返回trueAlert(null==undefined)//返回true2.4數值計算varmynum1=23.345;varmynum2=45;varmynum3=-34;varmynum4=9e5; //科學計數法為9*10五次方varfNumber=123.456;alert(fNumber.toExponential(1));//保留的小數點數1.2e+2alert(fNumber.toExponential(2));//1.23e+2.5布爾值varmarried=true;alert("1."+typeof(married));//Booleanmarried="true";alert("2."+typeof(married));//String.6類型轉換轉換成string類型有三種方式vara=3;varb=a+"";varc=a.toString();vard="student"+a;toString()vara=11;document.write(a.toString(2)+"<br>");//轉成2進制document.write(a.toString(3)+"<br>");//轉成3進制如果不是數值,則轉換報錯parseInt()document.write(parseInt("1red6")+"<br>");//返回1,后面非數值的將全部忽略document.write(parseInt("53.5")+"<br>");//返回53document.write(parseInt("0xC")+"<br>"); //直接十進制轉換12document.write(parseInt("isaacshun@")+"<br>");//NANdocument.write(parseInt("011",8)+"<br>");返回9document.write(parseInt("011",10)+"<br>"); //指定為十進制返回11parseFloat()與parseInt()類似2.7數組varaMap=newArray("China","USA","Britain");aMap[20]="Korea";alert(aMap.length+""+aMap[10]+""+aMap[20]);//aMap[10]返回undefineddocument.write(aMap.join("][")+"<br>"); //用“][”來連接varsFruit="apple,pear,peach,orange";varaFruit=sFruit.split(",");varaFruit=["apple","pear","peach","orange"];alert(aFruit.reverse().toString());varaFruit=["pear","apple","peach","orange"];aFruit.sort();varstack=newArray();stack.push("red");stack.push("green");stack.push("blue");document.write(stack.toString()+"<br>");varvItem=stack.pop();//bluedocument.write(vItem+"<br>");document.write(stack.toString());//redgreen2.8if語句//首先獲取用戶的一個輸入,并用Number()強制轉換為數字variNumber=Number(prompt("輸入一個5到100之間的數字",""));//第二個參數,用于顯示輸入框的默認值if(isNaN(iNumber)) //判斷輸入的是否是數字NaN“NotaNumber” document.write("請確認你的輸入正確");elseif(iNumber>100||iNumber<5) //判斷輸入的數字范圍 document.write("你輸入的數字范圍不在5和100之間");else document.write("你輸入的數字是:"+iNumber);2.9switchiWeek=parseInt(prompt("輸入1到7之間的整數",""));switch(iWeek){ case1: document.write("Monday"); break; case2: document.write("Tuesday"); break; case3: document.write("Wednesday"); break; case4: document.write("Thursday"); break; case5: document.write("Friday"); break; case6: document.write("Saturday"); break; case7: document.write("Sunday"); break; default: document.write("Error");}2.10while語句vari=iSum=0;while(i<=100){ iSum+=i; i++;}alert(iSum);do.whileforbreakcontinue(與JAVA語法一致)2.11函數functionArgsNum(){ returnarguments.length;}document.write(ArgsNum("isaac",25)+"<br>");document.write(ArgsNum()+"<br>");document.write(ArgsNum(3)+"<br>");從這個例子可以看出,方法可以沒有參數,也可以沒有返回值,但是照樣可以傳入參數和返回值。2.12Date對象varmyDate1=newDate(); //運行代碼前的時間for(vari=0;i<3000000;i++);varmyDate2=newDate(); //運行代碼后的時間document.write(myDate2);varoMyDate=newDate();variYear=oMyDate.getFullYear();variMonth=oMyDate.getMonth()+1; //月份是從0開始的variDate=oMyDate.getDate();variDay=oMyDate.getDay();//0為星期日1為星期一functiondisDate(oDate,iDate){ varms=oDate.getTime(); //換成毫秒數 ms-=iDate*24*60*60*1000; //計算相差的毫秒數 returnnewDate(ms); //返回新的時間對象}varoBeijing=newDate(2008,7,8);variNum=100; //前100天varoMyDate=disDate(oBeijing,iNum);2.13檢測瀏覽器和操作系統varsUserAgent=navigator.userAgent;//檢測Opera、KHTMLvarisOpera=sUserAgent.indexOf("Opera")>-1;varisKHTML=sUserAgent.indexOf("KHTML")>-1||sUserAgent.indexOf("Konqueror")>-1||sUserAgent.indexOf("AppleWebKit")>-1;//檢測IE、MozillavarisIE=sUserAgent.indexOf("compatible")>-1&&sUserAgent.indexOf("MSIE")>-1&&!isOpera;varisMoz=sUserAgent.indexOf("Gecko")>-1&&!isKHTML;//檢測操作系統varisWin=(navigator.platform=="Win32")||(navigator.platform=="Windows");varisMac=(navigator.platform=="Mac68K")||(navigator.platform=="MacPPC")||(navigator.platform=="Macintosh");varisUnix=(navigator.platform=="X11")&&!isWin&&!isMac;if(isOpera)document.write("Opera");if(isKHTML)document.write("KHTML");if(isIE)document.write("IE");if(isMoz)document.write("Mozilla");if(isWin)document.write("Windows");if(isMac)document.write("Mac");if(isUnix)document.write("Unix");Global對象其實isNan,paraseInt等都是Global對象的方法EncodeURI.因為有效的URI不能包含某些字符,如空格。這個方法就是用于將這個字符轉換成UTF-8編碼,使瀏覽器可以接受他們。Varsuil=“/profile/a.html”;即將空格編碼成%20Eval方法Eval(“alert(‘hi’)”);當解析程序發現eval()時,它將把參數解析成真正的ECMA-script語句,然后插入該語句所在位置。Global除了有內置方法外,還有很多內置的屬性:如:undefined,nan,Array,String,Number,Date,RegExp等Math對象Max方法,min方法,ceil,floor,round,sqrt,randomMax(1,2,3);min(1.2,3.4);想取到1~10的數據Math.floor(Math.random()*10+1)2~9的數據Math.floor(Math.random()*9+2);3.1getElementsByTagNamefunctionsearchDOM(){ //放在函數內,頁面加載完成后才用<body>的onload加載,這時如果把alert這句改成用document.write則會把原內容覆蓋掉,因為是后面才執行的 varoLi=document.getElementsByTagName("li"); //輸出長度、標簽名稱以及某項的文本節點值 alert(oLi.length+""+oLi[0].tagName+""+oLi[3].childNodes[0].nodeValue); varoUl=document.getElementsByTagName("ul"); varoLi2=oUl[1].getElementsByTagName("li"); alert(oLi2.length+""+oLi2[0].tagName+""+oLi2[1].childNodes[0].nodeValue);}<bodyonload="searchDOM()"> <ul>客戶端語言 <li>HTML</li> <li>JavaScript</li> <liid="cssLi">CSS</li> </ul><ul>服務器端語言 <li>ASP.NET</li> <li>JSP</li> <li>PHP</li></ul></body>3.2getElementByIdvaroLi=document.getElementById("cssLi");oLi.style.backgroundColor="yellow" //輸出標簽名稱以及文本節點值 alert(oLi.tagName+""+oLi.childNodes[0].nodeValue);3.2getElementsByNamealert(document.getElementsByName("a").length);3.3訪問子節點functionmyDOMInspector(){ varoUl=document.getElementById("myList"); //獲取<ul>標記 varDOMString=""; if(oUl.hasChildNodes()){ //判斷是否有子節點 varoCh=oUl.childNodes; for(vari=0;i<oCh.length;i++) //逐一查找 DOMString+=oCh[i].nodeName+"\n"; } alert(DOMString);}4訪問父節點nodeName如果為文本節點,則返回#texttagName如果為文本節點,則返回undefinedfunctionmyDOMInspector(){ varmyItem=document.getElementById("myDearFood"); alert(myItem.parentNode.tagName);}functionmyDOMInspector(){ varmyItem=document.getElementById("myDearFood"); varparentElm=myItem.parentNode; while(parentElm.className!="colorful"&&parentElm!=document.body) parentElm=parentElm.parentNode; //一路往上找 alert(parentElm.tagName);}<bodyonload="myDOMInspector()"><divclass="colorful"><ul> <li>糖醋排骨</li> <li>圓籠粉蒸肉</li> <li>泡菜魚</li> <liid="myDearFood">板栗燒雞</li> <li>麻婆豆腐</li> </ul></div></body>訪問兄弟節點functionmyDOMInspector(){ varmyItem=document.getElementById("myDearFood"); //訪問兄弟節點 varnextListItem=myItem.nextSibling; varpreListItem=myItem.previousSibling; alert(nextListItem.tagName+""+preListItem.tagName);}在Firefox中不支持,但是IE中卻是支持的。3.6第一個最后一個子節點functionnextSib(node){ vartempLast=node.parentNode.lastChild; //判斷是否是最后一個節點,如果是則返回null if(node==tempLast) returnnull; vartempObj=node.nextSibling; //逐一搜索后面的兄弟節點,直到發現元素節點為止 while(tempObj.nodeType!=1&&tempObj.nextSibling!=null) tempObj=tempObj.nextSibling; //三目運算符,如果是元素節點則返回節點本身,否則返回null return(tempObj.nodeType==1)?tempObj:null;}functionprevSib(node){ vartempFirst=node.parentNode.firstChild; //判斷是否是第一個節點,如果是則返回null if(node==tempFirst) returnnull; vartempObj=node.previousSibling; //逐一搜索前面的兄弟節點,直到發現元素節點為止 while(tempObj.nodeType!=1&&tempObj.previousSibling!=null) tempObj=tempObj.previousSibling; return(tempObj.nodeType==1)?tempObj:null;}functionmyDOMInspector(){ varmyItem=document.getElementById("myDearFood"); //獲取后一個元素兄弟節點 varnextListItem=nextSib(myItem); //獲取前一個元素兄弟節點 varpreListItem=prevSib(myItem); alert("后一項:"+((nextListItem!=null)?nextListItem.firstChild.nodeValue:null)+"前一項:"+((preListItem!=null)?preListItem.firstChild.nodeValue:null));}nodeType元素element1屬性attr2文本text3注釋comments8文檔document9functionshowAttr(){varbtnShowAttr=document.getElementById("btnShowAttr");//演示按鈕,有很多屬性varattrs=btnShowAttr.attributes;for(vari=0;i<attrs.length;i++){varattr=attrs[i];alert('nodeType:'+attr.nodeType);//attribute的nodeType=2alert('attr:'+attr);alert(':'++'='+attr.value);}functionshowDocument(){alert('nodeType:'+document.nodeType);//9alert('nodeName:'+document.nodeName);alert(document);}3.7getAttributesetAttributefunctionmyDOMInspector(){ //獲取圖片 varmyImg=document.getElementsByTagName("img")[0]; //獲取圖片title屬性 alert(myImg.getAttribute("title"));}functionchangePic(){ //獲取圖片 varmyImg=document.getElementsByTagName("img")[0]; //設置圖片src和title屬性 myImg.setAttribute("src","02.jpg"); myImg.setAttribute("title","紫荊公寓");}3.8創建新節點functioncreateP(){ varop=document.createElement("p"); varotext=document.createTextNode("HHHHH"); op.appendChild(otext); op.setAttribute("style","text-align:center"); document.body.appendChild(op); //創建完節點,就馬上會影響到下面的操作,比如P的數量就會多1個}3.9刪除節點需要注意的是標簽之間的父子關系?。?!functiondeleteP(){ varoP=document.getElementsByTagName("p")[0]; oP.parentNode.removeChild(oP); //刪除節點}3.10替換節點functionreplaceP(){ varoOldP=document.getElementsByTagName("p")[0]; varoNewP=document.createElement("p"); //新建節點 varoText=document.createTextNode("這是一個感人肺腑的故事"); oNewP.appendChild(oText); oOldP.parentNode.replaceChild(oNewP,oOldP); //替換節點}3.11插入節點functioninsertP(){ varoOldP=document.getElementsByTagName("p")[0]; varoNewP=document.createElement("p"); //新建節點 varoText=document.createTextNode("這是一個感人肺腑的故事"); oNewP.appendChild(oText); oOldP.parentNode.insertBefore(oNewP,oOldP); //插入節點}沒有insertAfter,但是可以自己寫一個functioninsertAfter(newElement,targetElement){ varoParent=targetElement.parentNode; //首先找到目標元素的父元素 if(oParent.lastChild==targetElement) //如果目標元素已經是最后一個子元素了 oParent.appendChild(newElement); //則直接用appendChild()加到子元素列表的最后 else //否則用insertBefore()插入到目標元素的下一個兄弟元素之前 oParent.insertBefore(newElement,targetElement.nextSibling);}functioninsertP(){ varoOldP=document.getElementById("myTarget"); varoNewP=document.createElement("p"); //新建節點 varoText=document.createTextNode("這是一個感人肺腑的故事"); oNewP.appendChild(oText); insertAfter(oNewP,oOldP); //插入節點}其實這個也是通過insertBefore原理來實現的3.12cloneNode(deepBoolean)復制并返回當前節點的復制節點,這個復制得到的節點是一個孤立的節點,不在document樹中。復制原來節點的屬性值,包括ID屬性,所以在把這個新節點加到document之前,一定要修改ID屬性,以便使它保持唯一。當然如果ID的唯一性不重要可以不做處理。這個方法支持一個布爾參數,當deepBoolean設置true時,復制當前節點的所有子節點,包括該節點內的文本。<pid=”mypara”>11111</p>p=document.getElementById("mypara")pclone=p.cloneNode(true);p.parentNode.appendChild(pclone3.12文檔碎片functioninsertPs(){ varaColors=["red","green","blue","magenta","yellow","chocolate","black","aquamarine","lime","fuchsia","brass","azure","brown","bronze","deeppink","aliceblue","gray","copper","coral","feldspar","orange","orchid","pink","plum","quartz","purple"]; varoFragment=document.createDocumentFragment(); //創建文檔碎片 for(vari=0;i<aColors.length;i++){ varoP=document.createElement("p"); varoText=document.createTextNode(aColors[i]); oP.appendChild(oText); oFragment.appendChild(oP); //將節點先添加到碎片中 } document.body.appendChild(oFragment); //最后一次性添加到頁面}3.13innerHTMLfunctionmyDOMInnerHTML(){ varmyDiv=document.getElementById("myTest"); alert(myDiv.innerHTML); //直接顯示innerHTML的內容 //修改innerHTML,可直接添加代碼 myDiv.innerHTML="<imgsrc='01.jpg'title='情人坡'>";}innerHTML可同時顯示沒有的代碼3.14換皮膚<styletype="text/css">.myUL1{ color:#0000FF; font-family:Arial; font-weight:bold;}.myUL2{ color:#FF0000; font-family:Georgia,"TimesNewRoman",Times,serif;}</style><scriptlanguage="javascript">functioncheck(){ varoMy=document.getElementsByTagName("ul")[0]; oMy.className=(oMy.className=="myUL1"?"myUL2":"myUL1"); //修改CSS類}</script></head><body> <ulonclick="check()"class="myUL1"> <li>HTML</li> <li>JavaScript</li> <li>CSS</li> </ul></body>4.表格與表單4.1動態添加行<scriptlanguage="javascript">window.onload=function(){ varoTr=document.getElementById("member").insertRow(2); //插入一行 varaText=newArray(); aText[0]=document.createTextNode("fresheggs"); aText[1]=document.createTextNode("W610"); aText[2]=document.createTextNode("Nov5th"); aText[3]=document.createTextNode("Scorpio"); aText[4]=document.createTextNode("1038818"); for(vari=0;i<aText.length;i++){ varoTd=oTr.insertCell(i); oTd.appendChild(aText[i]); }}</script>4.2修改單元格內容<scriptlanguage="javascript">window.onload=function(){ varoTable=document.getElementById("member"); oTable.rows[3].cells[4].innerHTML="lost"; //修改單元格內容}</script>4.3動態刪除parentElement是IEdom,parentNode是標準DOM<scriptlanguage="javascript">window.onload=function(){ varoTable=document.getElementById("member"); oTable.deleteRow(2); //刪除一行,后面的行號自動補齊//指從table中的第2行開始進行刪除 oTable.rows[2].deleteCell(1); //刪除一個單元格,后面的也自動補齊}</script><scriptlanguage="javascript">functionmyDelete(){ varoTable=document.getElementById("member"); //刪除該行 this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode);}window.onload=function(){ varoTable=document.getElementById("member"); varoTd; //動態添加delete鏈接 for(vari=1;i<oTable.rows.length;i++){ oTd=oTable.rows[i].insertCell(5); oTd.innerHTML="<ahref='#'>delete</a>"; oTd.firstChild.onclick=myDelete; //添加刪除事件 }}</script>4.4動態刪除列<scriptlanguage="javascript">functiondeleteColumn(oTable,iNum){ //自定義刪除列函數,即每行刪除相應單元格 for(vari=0;i<oTable.rows.length;i++) oTable.rows[i].deleteCell(iNum);}window.onload=function(){ varoTable=document.getElementById("member"); deleteColumn(oTable,2);}</script>4.5控制textarea的字符個數<scriptlanguage="javascript">functionLessThan(oTextArea){ //返回文本框字符個數是否符號要求的boolean值 returnoTextArea.value.length<oTextArea.getAttribute("maxlength");}</script>5.BOM模型瀏覽器對象模型,可以對瀏覽器窗口進行訪問和操作,使用BOM,開發者可以移動窗口,改變狀態欄中的文本等與頁面內容不相關的操作Window對象這里可以用window.frames[0]或者用windows.frames[“topFrame”]來引用框架,也可以用topl來代替window屬性。Top.frames[0]。window對象可以忽略提供的方法有moveto,moveBy,resizeTo,resizeBy等方法。但盡量避免使用它們,因為會對用戶瀏覽產生影響Open方法除了open方法,還有alert,comfirm,prompt方法狀態欄Settimeout與setIntervalSettimeout下面的代碼都是在1秒鐘后顯示一條警告Settimeout(“alert(‘aa’),1000”);Settimeout(function(){alert(‘aa’);},1000);如果要還未執行的暫停,可調用clearTimeOut()方法Varsi=Settimeout(function(){alert(‘aa’);},1000);clearTimeout(si);setIntervalHistory向后一頁window.history.go(-1);等于history.back();向前一頁window.history.go(1);等于history.forword();DocumentLastModified,title,URL屬性都是比較常用Location對象Navigator對象Screen對象6.事件6.1冒泡型事件<scriptlanguage="javascript">functionadd(sText){ varoDiv=document.getElementById("display"); oDiv.innerHTML+=sText; //輸出點擊順序}</script></head><bodyonclick="add('body<br>');"> <divonclick="add('div<br>');"> <ponclick="add('p<br>');">ClickMe</p> </div> <divid="display"></div></body>先執行最里面的p,再往外執行6.2監聽函數<scriptlanguage="javascript">window.onload=function(){ varoP=document.getElementById("myP"); //找到對象 oP.onclick=function(){ //設置事件監聽函數 alert('我被點擊了'); }}</script></head><body> <div> <pid="myP">ClickMe</p> </div></body>Functiona(){}oP.onclick=a這樣會先把a函數加載到緩存,不是最佳方案VarA=Function(){}oP.onclick=a這樣只有在onclick事件發生的時候,加載該函數若以上的監聽函數,在onclick的時候,需要執行多個函數,那就只能用以下的方法:IE標準:<scriptlanguage="javascript">functionfnClick(){ alert("我被點擊了"); oP.detachEvent("onclick",fnClick); //點擊了一次后刪除監聽函數}varoP;//聲明在函數外,這樣就可以兩個函數一起使用window.onload=function(){ oP=document.getElementById("myP"); //找到對象 oP.attachEvent("onclick",fnClick); //添加監聽函數}</script></head><body> <div> <pid="myP">ClickMe</p> </div></body> 也可以添加多個監聽器oP.attachEvent("onclick",fnClick1); //添加監聽函數1 oP.attachEvent("onclick",fnClick2); //添加監聽函數2執行順序為fnClick2->fnClick1但是以上的監聽器均為IE中的標準,而符合標準DOM(firefox)的監聽器如下oP.addEventListener("click",fnClick1,false); //添加監聽函數1 oP.addEventListener("click",fnClick2,false); //添加監聽函數2因此這種方式在Firefox中支持,而在IE中不支持為了兼容性,可這樣寫if

(el.addEventListener){

el.addEventListener('click',

KindDisableMenu,

false);

}

else

if

(el.attachEvent){

el.attachEvent('onclick',

KindDisableMenu);

}第三個參數為useCapture而useCapture這個參數就是在控制這時候兩個click事件的先後順序。如果是false,那就會使用bubbling,他是從內而外的流程,所以會先執行藍色元素的click事件再執行紅色元素的click事件,如果是true,那就是capture,和bubbling相反是由外而內6.3事件的類型event.typeIE瀏覽器中事件對象是window對象的一個屬性eventOp.onlick=function(){varo=window.event}而標準DOM中規定event對象必須作為唯一的參數傳給事件處理函數Op.onclick=function(oevent){}因此為了兼容兩種瀏覽器,通常采用下面的方法Op.onclick=function(o){If(window.event)//假如不等于空,則為IE瀏覽器 O=window.event;}<scriptlanguage="javascript">functionhandle(oEvent){ varoDiv=document.getElementById("display"); if(window.event)oEvent=window.event; //處理兼容性,獲得事件對象 if(oEvent.type=="click") //檢測事件名稱 oDiv.innerHTML+="你點擊了我  "; elseif(oEvent.type=="mouseover") oDiv.innerHTML+="你移動到我上方了  "; }window.onload=function(){ varoImg=document.getElementsByTagName("img")[0]; oImg.onclick=handle; oImg.onmouseover=handle;}</script>還有很多鼠標事件window.onload=function(){ varoImg=document.getElementsByTagName("img")[0]; oImg.onmousedown=handle; //將鼠標事件除了mousemove外都監聽 oImg.onmouseup=handle; oImg.onmouseover=handle; oImg.onmouseout=handle; oImg.onclick=handle; oImg.ondblclick=handle;}6.4事件的激活元素event.srcElement或者target<scriptlanguage="javascript">functionhandle(oEvent){ if(window.event)oEvent=window.event; //處理兼容性,獲得事件對象 varoTarget; if(oEvent.srcElement) //處理兼容性,獲取事件目標 oTarget=oEvent.srcElement;//IE支持的寫法 else oTarget=oEvent.target;//Firefox支持的寫法 alert(oTarget.tagName); //彈出目標的標記名稱 }window.onload=function(){ varoImg=document.getElementsByTagName("img")[0]; oImg.onclick=handle;}</script>event.button<scriptlanguage="javascript">functionTestClick(oEvent){ varoDiv=document.getElementById("display"); if(window.event) oEvent=window.event; oDiv.innerHTML+=oEvent.button; //輸出button的值}document.onmousedown=TestClick;window.onload=TestClick; //測試未按下任何鍵</script></head><body><divid="display"></div></body>在IE/Opera中,是window.event,而在Firefox中,是event

而事件的對象,在IE中是window.event.srcElement,在Firefox中是event.target,而在Opera中則兩者都支持。在IE里面

左鍵是window.event.button=1

右鍵是window.event.button=2

中鍵是window.event.button=4

沒有按鍵動作的時候window.event.button=0

在Firefox里面

左鍵是event.button=0

右鍵是event.button=2

中鍵是event.button=1

沒有按鍵動作的時候event.button=0

在Opera7.23/7.54里面

鼠標左鍵是window.event.button=1

沒有按鍵動作的時候window.event.button=1

右鍵和中鍵無法獲取鍵盤事件window.onload=function(){ varoTextArea=document.getElementsByTagName("textarea")[0]; oTextArea.onkeydown=handle; //監聽所有鍵盤事件 oTextArea.onkeyup=handle; oTextArea.onkeypress=handle;}e.keyCode;onkeypress是在用戶按下并放開任何字母數字鍵時發生。系統按鈕(例如,箭頭鍵和功能鍵,Shift、Ctrl、Alt、F1、F2)無法得到識別。

onkeyup是在用戶放開任何先前按下的鍵盤鍵時發生。

onkeydown是在用戶按下任何鍵盤鍵(包括系統按鈕,如箭頭鍵和功能鍵)時發生屏蔽鼠標右鍵第一種方式:<scriptlanguage="javascript">functionblock(oEvent){ if(window.event) oEvent=window.event; if(oEvent.button==2) alert("鼠標右鍵不可用");}document.onmousedown=block;</script>第二種方式:<scriptlanguage="javascript">functionblock(oEvent){ if(window.event){ oEvent=window.event; oEvent.returnValue=false; //取消默認事件支持IE }else oEvent.preventDefault(); //取消默認事件支持Firefox}document.oncontextmenu=block;</script>6.8伸縮的菜單<scriptlanguage="javascript">functionchange(){ //通過父元素li,找到兄弟元素ul varoSecondDiv=this.parentNode.getElementsByTagName("ul")[0];//這里的this就是下面的OA //CSS交替更換來實現顯、隱 if(oSecondDiv.className=="myHide") oSecondDiv.className="myShow"; else oSecondDiv.className="myHide";}window.onload=function(){ varoUl=document.getElementById("listUL"); varaLi=oUl.childNodes; //子元素 varoA; for(vari=0;i<aLi.length;i++){ //如果子元素為li,且這個li有子菜單ul

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論