頁面優化大全

前端是龐大的,包括HTML、CSS、Javascript、Image、Flash等等各種各樣的資源。前端優化是複雜的,針對方方面面的資源都有不同的方式。那麼,前端優化的目的是什麼

 

1. 從用戶角度而言,優化能夠讓頁面加載得更快、對用戶的操作響應得更及時,能夠給用戶提供更爲友好的體驗。

2. 從服務商角度而言,優化能夠減少頁面請求數、或者減小請求所佔帶寬,能夠節省可觀的資源。

總之,恰當的優化不僅能夠改善站點的用戶體驗並且能夠節省相當的資源利用。

前端優化的途徑有很多,按粒度大致可以分爲兩類,第一類是頁面級別的優化,例如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,可以節省帶寬)

怎樣纔算合理設置?原則很簡單,能緩存越多越好,能緩存越久越好。例如,很少變化的圖片資源可以直接通過HTTP Header中的Expires設置一個很長的過期頭;變化不頻繁而又可能會變的資源可以使用Last-Modifed來做請求驗證。儘可能的讓資源能夠在緩存中待得更久。關於HTTP緩存的具體設置和原理此處就不再詳述了,有興趣的可以參考下列文章:

HTTP1.1協議中關於緩存策略的描述

Fiddler HTTP Performance中關於緩存的介紹

 

(3). 資源合併與壓縮

如果可以的話,儘可能的將外部的腳本、樣式進行合併,多個合爲一個。另外,CSS、Javascript、Image都可以用相應的工具進行壓縮,壓縮後往往能省下不少空間。

 

(4). CSS Sprites

合併CSS圖片,減少請求數的又一個好辦法。

 

(5). Inline Images

使用data: URL scheme的方式將圖片嵌入到頁面或CSS中,如果不考慮資源管理上的問題的話,不失爲一個好辦法。如果是嵌入頁面的話換來的是增大了頁面的體積,而且無法利用瀏覽器緩存。使用在CSS中的圖片則更爲理想一些

 

(6). Lazy Load Image

這條策略實際上並不一定能減少HTTP請求數,但是卻能在某些條件下或者頁面剛加載時減少HTTP請求數。對於圖片而言,在頁面剛加載的時候可以只加載第一屏,當用戶繼續往後滾屏的時候才加載後續的圖片。這樣一來,假如用戶只對第一屏的內容感興趣時,那剩餘的圖片請求就都節省了。有啊首頁曾經的做法是在加載的時候把第一屏之後的圖片地址緩存在Textarea標籤中,待用戶往下滾屏的時候才”惰性”加載。

 

2. 將外部腳本置底

前文有談到,瀏覽器是可以併發請求的,這一特點使得其能夠更快的加載資源,然而外鏈腳本在加載時卻會阻塞其他資源,例如在腳本加載完成之前,它後面的圖片、樣式以及其他腳本都處於阻塞狀態,直到腳本加載完成後纔會開始加載。如果將腳本放在比較靠前的位置,則會影響整個頁面的加載速度從而影響用戶體驗。解決這一問題的方法有很多,在這裏有比較詳細的介紹(這裏是譯文和更詳細的例子),而最簡單可依賴的方法就是將腳本儘可能的往後挪,減少對併發下載的影響。

 

3. 異步執行inline腳本

inline腳本對性能的影響與外部腳本相比,是有過之而無不及。首頁,與外部腳本一樣,inline腳本在執行的時候一樣會阻塞併發請求,除此之外,由於瀏覽器在頁面處理方面是單線程的,當inline腳本在頁面渲染之前執行時,頁面的渲染工作則會被推遲。簡而言之,inline腳本在執行的時候,頁面處於空白狀態。鑑於以上兩點原因,建議將執行時間較長的inline腳本異步執行,異步的方式有很多種,例如使用script元素的defer屬性(存在兼容性問題和其他一些問題,例如不能使用document.write)、使用setTimeout,此外,在HTML5中引入了Web Workers的機制,恰恰可以解決此類問題

 

4. Lazy Load Javascript

隨着Javascript框架的流行,越來越多的站點也使用起了框架。不過,一個框架往往包括了很多的功能實現,這些功能並不是每一個頁面都需要的,如果下載了不需要的腳本則算得上是一種資源浪費-既浪費了帶寬又浪費了執行花費的時間。目前的做法大概有兩種,一種是爲那些流量特別大的頁面專門定製一個專用的mini版框架,另一種則是Lazy Load。YUI則使用了第二種方式,在YUI的實現中,最初只加載核心模塊,其他模塊可以等到需要使用的時候才加載

 

5. 將CSS放在HEAD中

如果將CSS放在其他地方比如BODY中,則瀏覽器有可能還未下載和解析到CSS就已經開始渲染頁面了,這就導致頁面由無CSS狀態跳轉到CSS狀態,用戶體驗比較糟糕。除此之外,有些瀏覽器會在CSS下載完成後纔開始渲染頁面,如果CSS放在靠下的位置則會導致瀏覽器將渲染時間推遲。

 

6. 異步請求Callback

在某些頁面中可能存在這樣一種需求,需要使用script標籤來異步的請求數據。類似:

Javascript:

/*Callback函數*/  
function myCallback(info){  
//do something here  

HTML:

<script type=”text/javascript” src=”http://abc.com/cb”></script> 

cb返回的內容:

myCallback(‘Hello world!’); 

      像以上這種方式直接在頁面上寫<script>對頁面的性能也是有影響的,即增加了頁面首次加載的負擔,推遲了DOMLoaded和window.onload事件的觸發時機。如果時效性允許的話,可以考慮在DOMLoaded事件觸發的時候加載,或者使用setTimeout方式來靈活的控制加載的時機。

 

7. 減少不必要的HTTP跳轉

對於以目錄形式訪問的HTTP鏈接,很多人都會忽略鏈接最後是否帶’/’,假如你的服務器對此是區別對待的話,那麼你也需要注意,這其中很可能隱藏了301跳轉,增加了多餘請求。具體參見下圖,其中第一個鏈接是以無’/’結尾的方式訪問的,於是服務器有了一次跳轉。

 

8. 避免重複的資源請求

這種情況主要是由於疏忽或頁面由多個模塊拼接而成,然後每個模塊中請求了同樣的資源時,會導致資源的重複請求

 

二、代碼級優化

1. Javascript

(1). DOM

DOM操作應該是腳本中最耗性能的一類操作,例如增加、修改、刪除DOM元素或者對DOM集合進行操作。如果腳本中包含了大量的DOM操作則需要注意以下幾點:

a. HTML Collection

在腳本中document.images、document.forms、getElementsByTagName()返回的都是HTMLCollection類型的集合,在平時使用的時候大多將它作爲數組來使用,因爲它有length屬性,也可以使用索引訪問每一個元素。不過在訪問性能上則比數組要差很多,原因是這個集合並不是一個靜態的結果,它表示的僅僅是一個特定的查詢,每次訪問該集合時都會重新執行這個查詢從而更新查詢結果。所謂的”訪問集合”包括讀取集合的length屬性、訪問集合中的元素。

因此,當你需要遍歷HTML Collection的時候,儘量將它轉爲數組後再訪問,以提高性能。即使不轉換爲數組,也請儘可能少的訪問它,例如在遍歷的時候可以將length屬性、成員保存到局部變量後再使用局部變量。

b. Reflow & Repaint

除了上面一點之外,DOM操作還需要考慮瀏覽器的Reflow和Repaint,因爲這些都是需要消耗資源的,具體的可以參加以下文章:

如何減少瀏覽器的repaint和reflow?

Understanding Internet Explorer Rendering Behaviour

Notes on HTML Reflow

 

(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). 減少作用域鏈查找

前文談到了作用域鏈查找問題,這一點在循環中是尤其需要注意的問題。如果在循環中需要訪問非本作用域下的變量時請在遍歷之前用局部變量緩存該變量,並在遍歷結束後再重寫那個變量,這一點對全局變量尤其重要,因爲全局變量處於作用域鏈的最頂端,訪問時的查找次數是最多的。

低效率的寫法:

//全局變量  
var globalVar = 1;  
function myCallback(info){  
   for( var i = 100000; i–;){  
      //每次訪問globalVar都需要查找到作用域鏈最頂端,本例中需要訪問100000次  
      globalVar += i;  
   } 

更高效的寫法:

//全局變量  
var globalVar = 1;  
function myCallback(info){  
   //局部變量緩存全局變量  
   var localVar = globalVar;  
   for( var i = 100000; i–;){  
      //訪問局部變量是最快的  
      localVar += i;  
   }  
   //本例中只需要訪問2次全局變量  
   globalVar = localVar;  
}

此外,要減少作用域鏈查找還應該減少閉包的使用。

(5). 數據訪問

Javascript中的數據訪問包括直接量(字符串、正則表達式)、變量、對象屬性以及數組,其中對直接量和局部變量的訪問是最快的,對對象屬性以及數組的訪問需要更大的開銷。當出現以下情況時,建議將數據放入局部變量:

a. 對任何對象屬性的訪問超過1次

b. 對任何數組成員的訪問次數超過1次

另外,還應當儘可能的減少對對象以及數組深度查找。

(6). 字符串拼接

在Javascript中使用”+”號來拼接字符串效率是比較低的,因爲每次運行都會開闢新的內存並生成新的字符串變量,然後將拼接結果賦值給新變量。與之相比更爲高效的做法是使用數組的join方法,即將需要拼接的字符串放在數組中最後調用其join方法得到結果。不過由於使用數組也有一定的開銷,因此當需要拼接的字符串較多的時候可以考慮用此方法。

關於Javascript優化的更詳細介紹請參考:

Write Efficient Javascript(PPT)

Efficient JavaScript

2. CSS選擇符

在大多數人的觀念中,都覺得瀏覽器對CSS選擇符的解析式從左往右進行的,例如

#toc A { color: #444; } 

這樣一個選擇符,如果是從右往左解析則效率會很高,因爲第一個ID選擇基本上就把查找的範圍限定了,但實際上瀏覽器對選擇符的解析是從右往左進行的。如上面的選擇符,瀏覽器必須遍歷查找每一個A標籤的祖先節點,效率並不像之前想象的那樣高。根據瀏覽器的這一行爲特點,在寫選擇符的時候需要注意很多事項,有人已經一一列舉了,詳情參考此處

3. HTML

對HTML本身的優化現如今也越來越多的受人關注了,詳情可以參見這篇總結性文章

4. Image壓縮

圖片壓縮是個技術活,不過現如今這方面的工具也非常多,壓縮之後往往能帶來不錯的效果,具體的壓縮原理以及方法在《Even Faster Web Sites》第10章有很詳細的介紹,有興趣的可以去看看。

總結

本文從頁面級以及代碼級兩個粒度對前端優化的各種方式做了一個總結,這些方法基本上都是前端開發人員在開發的過程中可以借鑑和實踐的,除此之外,完整的前端優化還應該包括很多其他的途徑,例如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,但後來不得不加入javascript

IE3中搭載Javascipt的克隆版本,命名爲jscript

在一次技術會議中,sun,microsoft,netscape公司聯合制定了ECMA-Script標準

在2005前,網頁上提示框,廣告越來越多,把javascipt濫用,使javascript背上了大量的罪名。

2005年,google公司的網上產品(google地圖,gmail,google搜索建議)等使得ajax興起,而javascript便是ajax最重要的元素之一

Javascript有三個部分組成

ECMAScript DOM BOM

WEB標準

網頁主要有三部分組成

(結構HTML,XHTML,表現CSS,行爲DOM,ECMA)

2.ECMA腳本

Javascript的語法

  1. 區分大小寫
  2. 弱類型變量 var age=10 var name=”dd”
  3. 每行結尾的分號可有可無,但建議還是加上
  4. 註釋與java相同

 

變量

變量是通過var關鍵字來聲明的。(Variable)

變量的命名規則與java一致

註釋有三種:// /**/ <!– –>這個只能註釋單行

2.1 javascript的Hello world

document.write()是寫在文檔的最前面

2.2 slice()、substring()、subtr

Slice和substring (2,5) 指的是從第3爲開始,取(5-2)=3個數,其中slice的參數可以爲負

Substr(2,5)指的是從第3爲開始,取5個數。但ECMAscript 沒有對該方法進行標準化,因此儘量少使用該方法

2.3 indexOf()和lastIndexOf(),isNan,typeOf

indexOf(”i”) //從前往後,i在第幾位

indexOf(”i”,3)可選參數,從第幾個字符開始往後找

lastIndexOf(”i”) //從後往前,i在第幾位

lastIndexOf(“i”,3) //從後往前,i在第幾位

如果沒找到,則返回-1

String類型的變量,在Java中,用””符號表示字符串,用”表示單個字符。而在javascript中這兩種都可以

Nan(not a number)

Alert(nan ==nan)返回false,因此不推薦使用nan本身,推薦函數isNan

Alert(isNanN(“ab”));//返回false

typeof運算符

var stmp = “test”;

alert(typeof stmp); //輸出string

alert(type of 1);//輸出number

此外:還有boolean,undefined,object(如果是引用類型或者null值,null值返回object,這其實是ecmascript的一個錯誤)

當聲明的變量未初始化的時候,它的值就是undefined.當沒有這個變量的時候,typeof 變

返回的值也是undefined。但是沒聲明的變量是不能參與計算的。

當函數無明確返回值時,返回的也是undefined

Function a(){

}

Alert(a() == undefined) //返回true

Alert(null == undefined)//返回true

2.4 數值計算

var mynum1 = 23.345;

var mynum2 = 45;

var mynum3 = -34;

var mynum4 = 9e5;        //科學計數法爲 9*10五次方

var fNumber = 123.456;

alert(fNumber.toExponential(1));//保留的小數點數 1.2e+2

alert(fNumber.toExponential(2));//1.23e+2

.5 布爾值

var married = true;

alert(“1.” + typeof(married));//Boolean

married = “true”;

alert(“2.” + typeof(married));//String

.6 類型轉換

轉換成string類型有三種方式

var a = 3;

var b = a + “”;

var c = a.toString();

var d = “student” + a;

 

toString()

var a=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>”);//返回53

document.write(parseInt(“0xC”) + “<br>”);    //直接十進制轉換12

document.write(parseInt(“[email protected]”) + “<br>”);//NAN

document.write(parseInt(“011″,8) + “<br>”);返回9

document.write(parseInt(“011″,10) + “<br>”);    //指定爲十進制返回11

 

parseFloat()與parseInt()類似

 

2.7 數組

var aMap = new Array(“China”,”USA”,”Britain”);

aMap[20] = “Korea”;

alert(aMap.length + ” ” + aMap[10] + ” ” + aMap[20]);//aMap[10]返回undefined

 

document.write(aMap.join(“][") + "<br>");        //用"]["來連接

 

 

var sFruit = "apple,pear,peach,orange";

var aFruit = sFruit.split(",");

 

var aFruit = ["apple","pear","peach","orange"];

alert(aFruit.reverse().toString());

 

var aFruit = ["pear","apple","peach","orange"];

aFruit.sort();

 

var stack = new Array();

stack.push(“red”);

stack.push(“green”);

stack.push(“blue”);

document.write(stack.toString() + “<br>”);

var vItem = stack.pop(); // blue

document.write(vItem + “<br>”);

document.write(stack.toString()); // red green

 

2.8 if語句

//首先獲取用戶的一個輸入,並用Number()強制轉換爲數字

var iNumber = Number(prompt(“輸入一個5到100之間的數字”, “”));//第二個參數,用於顯示輸入框的默認值

if(isNaN(iNumber))        //判斷輸入的是否是數字NaN “Not a Number”

    document.write(“請確認你的輸入正確”);

else if(iNumber > 100 || iNumber < 5)        //判斷輸入的數字範圍

    document.write(“你輸入的數字範圍不在5和100之間”);

else

    document.write(“你輸入的數字是:” + iNumber);

2.9 switch

 

iWeek = parseInt(prompt(“輸入1到7之間的整數”,””));

switch(iWeek){

    case 1:

        document.write(“Monday”);

        break;

    case 2:

        document.write(“Tuesday”);

        break;

    case 3:

        document.write(“Wednesday”);

        break;

    case 4:

        document.write(“Thursday”);

        break;

    case 5:

        document.write(“Friday”);

        break;

    case 6:

        document.write(“Saturday”);

        break;

    case 7:

        document.write(“Sunday”);

        break;

    default:

        document.write(“Error”);

}

2.10 while語句

var i=iSum=0;

while(i<=100){

    iSum += i;

    i++;

}

alert(iSum);

do.while for break continue (與JAVA語法一致)

2.11 函數

function ArgsNum(){

    return arguments.length;

}

document.write(ArgsNum(“isaac”,25) + “<br>”);

document.write(ArgsNum() + “<br>”);

document.write(ArgsNum(3) + “<br>”);

從這個例子可以看出,方法可以沒有參數,也可以沒有返回值,但是照樣可以傳入參數和返回值

2.12 Date對象

var myDate1 = new Date();    //運行代碼前的時間

for(var i=0;i<3000000;i++);

var myDate2 = new Date();    //運行代碼後的時間

document.write(myDate2);

 

var oMyDate = new Date();

var iYear = oMyDate.getFullYear();

var iMonth = oMyDate.getMonth() + 1;    //月份是從0開始的

var iDate = oMyDate.getDate();

var iDay = oMyDate.getDay(); //0 爲星期日 1 爲星期一

function disDate(oDate, iDate){

    var ms = oDate.getTime();        //換成毫秒數

    ms -= iDate*24*60*60*1000;        //計算相差的毫秒數

    return new Date(ms);            //返回新的時間對象

}

var oBeijing = new Date(2008,7,8);

var iNum = 100;                        //前100天

var oMyDate = disDate(oBeijing, iNum);

 

2.13 檢測瀏覽器和操作系統

var sUserAgent = navigator.userAgent;

//檢測Opera、KHTML

var isOpera = sUserAgent.indexOf(“Opera”) > -1;

var isKHTML = sUserAgent.indexOf(“KHTML”) > -1 || sUserAgent.indexOf(“Konqueror”) > -1 || sUserAgent.indexOf(“AppleWebKit”) > -1;

//檢測IE、Mozilla

var isIE = sUserAgent.indexOf(“compatible”) > -1 && sUserAgent.indexOf(“MSIE”) > -1 && !isOpera;

var isMoz = sUserAgent.indexOf(“Gecko”) > -1 && !isKHTML;

//檢測操作系統

var isWin = (navigator.platform == “Win32″) || (navigator.platform == “Windows”);

var isMac = (navigator.platform == “Mac68K”) || (navigator.platform == “MacPPC”) || (navigator.platform == “Macintosh”);

var isUnix = (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”);

 

  1. Global對象

     

    其實isNan,paraseInt等都是Global對象的方法

     

    EncodeURI.因爲有效的URI不能包含某些字符,如空格。這個方法就是用於將這個字符轉換成UTF-8編碼,使瀏覽器可以接受他們。

     

    Var suil = “www.oseschool.com/pro file/a.html”;

    Alert(encodeURI(suil));//www.oseschool.com/pro%20file/a.html

     

    即將空格編碼成%20

     

    Eval方法

    Eval(“alert(‘hi’)”);

    當解析程序發現eval()時,它將把參數解析成真正的ECMA-script語句,然後插入該語句所在位置。

     

    Global除了有內置方法外,還有很多內置的屬性:如:undefined,nan,Array,String,Number,Date,RegExp等

  2. Math對象

     

    Max方法,min方法,ceil,floor,round,sqrt,random

     

    Max(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.1 getElementsByTagName

function searchDOM(){

    //放在函數內,頁面加載完成後才用<body>的onload加載,這時如果把alert這句改成用document.write則會把原內容覆蓋掉,因爲是後面才執行的

    var oLi = document.getElementsByTagName(“li”);

    //輸出長度、標籤名稱以及某項的文本節點值

    alert(oLi.length + ” ” +oLi[0].tagName + ” ” + oLi[3].childNodes[0].nodeValue);

    

    var oUl = document.getElementsByTagName(“ul”);

    var oLi2 = oUl[1].getElementsByTagName(“li”);

    alert(oLi2.length + ” ” +oLi2[0].tagName + ” ” + oLi2[1].childNodes[0].nodeValue);

}

<body onload=”searchDOM()”>

    <ul>客戶端語言

        <li>HTML</li>

        <li>JavaScript</li>

        <li id=”cssLi”>CSS</li>

    </ul>

<ul>服務器端語言

        <li>ASP.NET</li>

        <li>JSP</li>

        <li>PHP</li>

</ul>

</body>

3.2 getElementById

var oLi = document.getElementById(“cssLi”);

oLi.style .backgroundColor=”yellow”

    //輸出標籤名稱以及文本節點值

    alert(oLi.tagName + ” ” + oLi.childNodes[0].nodeValue);

3.2 getElementsByName

alert(document.getElementsByName(“a”).length);

3.3 訪問子節點

function myDOMInspector(){

    var oUl = document.getElementById(“myList”);    //獲取<ul>標記

    var DOMString = “”;

    if(oUl.hasChildNodes()){                        //判斷是否有子節點

        var oCh = oUl.childNodes;

        for(var i=0;i<oCh.length;i++)                //逐一查找

            DOMString += oCh[i].nodeName + “\n”;

    }

    alert(DOMString);

}

4訪問父節點

nodeName如果爲文本節點,則返回#text

tagName如果爲文本節點,則返回undefined

 

function myDOMInspector(){

    var myItem = document.getElementById(“myDearFood”);

    alert(myItem.parentNode.tagName);

}

 

function myDOMInspector(){

    var myItem = document.getElementById(“myDearFood”);

    var parentElm = myItem.parentNode;

    while(parentElm.className != “colorful” && parentElm != document.body)

        parentElm = parentElm.parentNode;    //一路往上找

    alert(parentElm.tagName);

}

<body onload=”myDOMInspector()”>

<div class=”colorful”>

<ul>

        <li>糖醋排骨</li>

        <li>圓籠粉蒸肉</li>

        <li>泡菜魚</li>

        <li id=”myDearFood”>板栗燒雞</li>

        <li>麻婆豆腐</li>

    </ul>

</div>

</body>

訪問兄弟節點

function myDOMInspector(){

    var myItem = document.getElementById(“myDearFood”);

    //訪問兄弟節點

    var nextListItem = myItem.nextSibling;

    var preListItem = myItem.previousSibling;

    alert(nextListItem.tagName +” “+ preListItem.tagName);

}

 

在Firefox中不支持,但是IE中卻是支持的。

3.6 第一個最後一個子節點

function nextSib(node){

    var tempLast = node.parentNode.lastChild;

    //判斷是否是最後一個節點,如果是則返回null

    if(node == tempLast)

        return null;

    var tempObj = node.nextSibling;

    //逐一搜索後面的兄弟節點,直到發現元素節點爲止

    while(tempObj.nodeType!=1 && tempObj.nextSibling!=null)

        tempObj = tempObj.nextSibling;

    //三目運算符,如果是元素節點則返回節點本身,否則返回null

    return (tempObj.nodeType==1)?tempObj:null;

}

function prevSib(node){

    var tempFirst = node.parentNode.firstChild;

    //判斷是否是第一個節點,如果是則返回null

    if(node == tempFirst)

        return null;

    var tempObj = node.previousSibling;

    //逐一搜索前面的兄弟節點,直到發現元素節點爲止

    while(tempObj.nodeType!=1 && tempObj.previousSibling!=null)

        tempObj = tempObj.previousSibling;

    return (tempObj.nodeType==1)?tempObj:null;

}

function myDOMInspector(){

    var myItem = document.getElementById(“myDearFood”);

    //獲取後一個元素兄弟節點

    var nextListItem = nextSib(myItem);

    //獲取前一個元素兄弟節點

    var preListItem = prevSib(myItem);

    alert(“後一項:” + ((nextListItem!=null)?nextListItem.firstChild.nodeValue:null) + ” 前一項:” + ((preListItem!=null)?preListItem.firstChild.nodeValue:null) );

}

 

nodeType

元素element

1 

屬性attr

2 

文本text

3 

註釋comments

8 

文檔document

9 

 

function showAttr(){

var btnShowAttr=document.getElementById(“btnShowAttr”); //演示按鈕,有很多屬性

var attrs=btnShowAttr.attributes;

for(var i=0;i<attrs.length ;i++){

var attr=attrs[i];

alert(‘nodeType:’+attr.nodeType); //attribute 的nodeType=2

alert(‘attr:’+attr);

alert(‘attr.name:’+attr.name+’=’+attr.value);

 

}

 

 

function showDocument(){

alert(‘nodeType:’+document.nodeType); //9

alert(‘nodeName:’+document.nodeName);

alert(document);

}

3.7 getAttribute setAttribute

function myDOMInspector(){

    //獲取圖片

    var myImg = document.getElementsByTagName(“img”)[0];

    //獲取圖片title屬性

    alert(myImg.getAttribute(“title”));

}

 

function changePic(){

    //獲取圖片

    var myImg = document.getElementsByTagName(“img”)[0];

    //設置圖片src和title屬性

    myImg.setAttribute(“src”,”02.jpg”);

    myImg.setAttribute(“title”,”紫荊公寓”);

}

 

3.8創建新節點

 

function createP(){

    var op = document.createElement(“p”);

    var otext = document.createTextNode(“HHHHH”);

    op.appendChild(otext);

    op.setAttribute(“style”,”text-align:center”);

    document.body.appendChild(op);

 

    //創建完節點,就馬上會影響到下面的操作,比如P的數量就會多1個

}

 

3.9刪除節點

需要注意的是標籤之間的父子關係!!!

function deleteP(){

    var oP = document.getElementsByTagName(“p”)[0];

    oP.parentNode.removeChild(oP);        //刪除節點

}

 

 

3.10替換節點

 

function replaceP(){

    var oOldP = document.getElementsByTagName(“p”)[0];

    var oNewP = document.createElement(“p”);        //新建節點

    var oText = document.createTextNode(“這是一個感人肺腑的故事”);

    oNewP.appendChild(oText);

    oOldP.parentNode.replaceChild(oNewP,oOldP);        //替換節點

}

 

3.11插入節點

 

function insertP(){

    var oOldP = document.getElementsByTagName(“p”)[0];

    var oNewP = document.createElement(“p”);        //新建節點

    var oText = document.createTextNode(“這是一個感人肺腑的故事”);

    oNewP.appendChild(oText);

    oOldP.parentNode.insertBefore(oNewP,oOldP);        //插入節點

}

 

沒有insertAfter,但是可以自己寫一個

 

function insertAfter(newElement, targetElement){

    var oParent = targetElement.parentNode;    //首先找到目標元素的父元素

    if(oParent.lastChild == targetElement)    //如果目標元素已經是最後一個子元素了

        oParent.appendChild(newElement);    //則直接用appendChild()加到子元素列表的最後

    else                                //否則用insertBefore()插入到目標元素的下一個兄弟元素之前

        oParent.insertBefore(newElement,targetElement.nextSibling);

}

function insertP(){

    var oOldP = document.getElementById(“myTarget”);

    var oNewP = document.createElement(“p”);        //新建節點

    var oText = document.createTextNode(“這是一個感人肺腑的故事”);

    oNewP.appendChild(oText);

    insertAfter(oNewP,oOldP);        //插入節點

}

 

其實這個也是通過insertBefore原理來實現的

 

3.12 cloneNode(deepBoolean)

複製並返回當前節點的複製節點,這個複製得到的節點是一個孤立的節點,不在document樹中。複製原來節點的屬性值,包括ID屬性,所以在把這個新節點加到document之前,一定要修改ID屬性,以便使它保持唯一。當然如果ID的唯一性不重要可以不做處理。

這個方法支持一個布爾參數,當deepBoolean設置true時,複製當前節點的所有子節點,包括該節點內的文本。

<p id=”mypara”>11111</p>

p=document.getElementById(“mypara”)

pclone = p.cloneNode(true);

p.parentNode.appendChild(pclone

 

3.12文檔碎片

 

function insertPs(){

    var aColors = ["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"];

    var oFragment = document.createDocumentFragment();    //創建文檔碎片

    for(var i=0;i<aColors.length;i++){

        var oP = document.createElement(“p”);

        var oText = document.createTextNode(aColors[i]);

        oP.appendChild(oText);

        oFragment.appendChild(oP);        //將節點先添加到碎片中

    }

    document.body.appendChild(oFragment);    //最後一次性添加到頁面

}

 

 

3.13 innerHTML

function myDOMInnerHTML(){

    var myDiv = document.getElementById(“myTest”);

    alert(myDiv.innerHTML);        //直接顯示innerHTML的內容

    //修改innerHTML,可直接添加代碼

    myDiv.innerHTML = “<img src=’01.jpg’ title=’情人坡’>”;

}

 

innerHTML可同時顯示沒有的代碼

 

3.14 換皮膚

 

<style type=”text/css”>

.myUL1{

    color:#0000FF;

    font-family:Arial;

    font-weight:bold;

}

.myUL2{

    color:#FF0000;

    font-family:Georgia, “Times New Roman”, Times, serif;

}

</style>

<script language=”javascript”>

function check(){

    var oMy = document.getElementsByTagName(“ul”)[0];

    oMy.className =(oMy.className==”myUL1″? “myUL2″:”myUL1″);    //修改CSS類

}

</script>

</head>

 

<body>

    <ul onclick=”check()” class=”myUL1″>

        <li>HTML</li>

        <li>JavaScript</li>

        <li>CSS</li>

    </ul>

</body>

 

4.表格與表單

4.1 動態添加行

<script language=”javascript”>

window.onload=function(){

    var oTr = document.getElementById(“member”).insertRow(2);    //插入一行

    var aText = new Array();

    aText[0] = document.createTextNode(“fresheggs”);

    aText[1] = document.createTextNode(“W610″);

    aText[2] = document.createTextNode(“Nov 5th”);

    aText[3] = document.createTextNode(“Scorpio”);

    aText[4] = document.createTextNode(“1038818″);

    for(var i=0;i<aText.length;i++){

        var oTd = oTr.insertCell(i);

        oTd.appendChild(aText[i]);

    }

}

</script>

 

4.2修改單元格內容

<script language=”javascript”>

window.onload=function(){

    var oTable = document.getElementById(“member”);

    oTable.rows[3].cells[4].innerHTML = “lost”;        //修改單元格內容

}

</script>

 

4.3 動態刪除

parentElement是IE dom,

parentNode是標準DOM

 

<script language=”javascript”>

window.onload=function(){

    var oTable = document.getElementById(“member”);

    oTable.deleteRow(2);        //刪除一行,後面的行號自動補齊//指從table中的第2行開始進行刪除

    oTable.rows[2].deleteCell(1);    //刪除一個單元格,後面的也自動補齊

}

</script>

 

<script language=”javascript”>

function myDelete(){

    var oTable = document.getElementById(“member”);

    //刪除該行

    this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode);

}

window.onload=function(){

    var oTable = document.getElementById(“member”);

    var oTd;

    //動態添加delete鏈接

    for(var i=1;i<oTable.rows.length;i++){

        oTd = oTable.rows[i].insertCell(5);

        oTd.innerHTML = “<a href=’#’>delete</a>”;

        oTd.firstChild.onclick = myDelete;    //添加刪除事件

    }

}

</script>

 

4.4動態刪除列

<script language=”javascript”>

function deleteColumn(oTable,iNum){

    //自定義刪除列函數,即每行刪除相應單元格

    for(var i=0;i<oTable.rows.length;i++)

        oTable.rows[i].deleteCell(iNum);

}

window.onload=function(){

    var oTable = document.getElementById(“member”);

    deleteColumn(oTable,2);

}

</script>

 

4.5 控制textarea的字符個數

<script language=”javascript”>

function LessThan(oTextArea){

    //返回文本框字符個數是否符號要求的boolean值

    return oTextArea.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與setInterval

Settimeout

下面的代碼都是在1秒鐘後顯示一條警告

Settimeout(“alert(‘aa’),1000″);

Settimeout(function(){alert(‘aa’);},1000);

 

如果要還未執行的暫停,可調用clearTimeOut()方法

Var si = Settimeout(function(){alert(‘aa’);},1000);

clearTimeout(si);

 

setInterval

 

History

向後一頁window.history.go(-1); 等於history.back();

向前一頁window.history.go(1); 等於 history.forword();

 

Document

 

LastModified,title,URL屬性都是比較常用

 

Location對象

Navigator對象

Screen對象

6.事件

6.1 冒泡型事件

 

<script language=”javascript”>

function add(sText){

    var oDiv = document.getElementById(“display”);

    oDiv.innerHTML += sText;    //輸出點擊順序

}

</script>

</head>

<body onclick=”add(‘body<br>’);”>

    <div onclick=”add(‘div<br>’);”>

        <p onclick=”add(‘p<br>’);”>Click Me</p>

    </div>

    <div id=”display”></div>

</body>

 

先執行最裏面的p,再往外執行

 

6.2 監聽函數

<script language=”javascript”>

window.onload = function(){

    var oP = document.getElementById(“myP”);    //找到對象

    oP.onclick = function(){                    //設置事件監聽函數

        alert(‘我被點擊了’);

    }

}

</script>

</head>

 

<body>

    <div>

        <p id=”myP”>Click Me</p>

    </div>

</body>

 

 

Function a(){}

oP.onclick = a

這樣會先把a函數加載到緩存,不是最佳方案

Var A = Function(){}

oP.onclick = a

這樣只有在onclick事件發生的時候,加載該函數

 

 

若以上的監聽函數,在onclick的時候,需要執行多個函數,那就只能用以下的方法

 

IE標準:

 

<script language=”javascript”>

function fnClick(){

    alert(“我被點擊了”);

    oP.detachEvent(“onclick”,fnClick);        //點擊了一次後刪除監聽函數

}

var oP;//聲明在函數外,這樣就可以兩個函數一起使用

window.onload = function(){

    oP = document.getElementById(“myP”);    //找到對象

    oP.attachEvent(“onclick”,fnClick);        //添加監聽函數

}

</script>

</head>

 

<body>

    <div>

        <p id=”myP”>Click Me</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.type

IE瀏覽器中事件對象是window對象的一個屬性event

Op.onlick=function(){ var o = window.event}

而標準DOM中規定event對象必須作爲唯一的參數傳給事件處理函數

Op.onclick=function(oevent){

}

因此爲了兼容兩種瀏覽器,通常採用下面的方法

Op.onclick=function(o){

If(window.event)//假如不等於空,則爲IE瀏覽器

    O = window.event;

}

 

<script language=”javascript”>

function handle(oEvent){

    var oDiv = document.getElementById(“display”);

    if(window.event) oEvent = window.event;        //處理兼容性,獲得事件對象

    if(oEvent.type == “click”)                    //檢測事件名稱

        oDiv.innerHTML += “你點擊了我&nbsp&nbsp;”;

    else if( oEvent.type == “mouseover”)

        oDiv.innerHTML += “你移動到我上方了&nbsp&nbsp;”;

        

}

window.onload = function(){

    var oImg = document.getElementsByTagName(“img”)[0];

    oImg.onclick = handle;

    oImg.onmouseover = handle;

}

</script>

 

還有很多鼠標事件

 

window.onload = function(){

    var oImg = 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

 

<script language=”javascript”>

function handle(oEvent){

    if(window.event) oEvent = window.event;        //處理兼容性,獲得事件對象

    var oTarget;

    if(oEvent.srcElement)                //處理兼容性,獲取事件目標

        oTarget = oEvent.srcElement; //IE支持的寫法

    else

        oTarget = oEvent.target; //Firefox支持的寫法

    alert(oTarget.tagName);                //彈出目標的標記名稱        

}

window.onload = function(){

    var oImg = document.getElementsByTagName(“img”)[0];

    oImg.onclick = handle;

}

</script>

event.button

<script language=”javascript”>

function TestClick(oEvent){

    var oDiv = document.getElementById(“display”);

    if(window.event)

        oEvent = window.event;

    oDiv.innerHTML += oEvent.button;    //輸出button的值

}

document.onmousedown = TestClick;

window.onload = TestClick;    //測試未按下任何鍵

</script>

</head>

 

<body>

<div id=”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

在 Opera 7.23/7.54 裏面
鼠標左鍵是window.event.button=1
沒有按鍵動作的時候window.event.button=1
右鍵和中鍵無法獲取

鍵盤事件

window.onload = function(){

    var oTextArea = document.getElementsByTagName(“textarea”)[0];

    oTextArea.onkeydown = handle;    //監聽所有鍵盤事件

    oTextArea.onkeyup = handle;

    oTextArea.onkeypress = handle;

}

 

e.keyCode;

 

onkeypress是在用戶按下並放開任何字母數字鍵時發生。系統按鈕(例如,箭頭鍵和功能鍵, Shift、Ctrl、Alt、F1、F2)無法得到識別。
onkeyup 是在用戶放開任何先前按下的鍵盤鍵時發生。
onkeydown 是在用戶按下任何鍵盤鍵(包括系統按鈕,如箭頭鍵和功能鍵)時發生

屏蔽鼠標右鍵

第一種方式:

<script language=”javascript”>

function block(oEvent){

    if(window.event)

        oEvent = window.event;

    if(oEvent.button == 2)

        alert(“鼠標右鍵不可用”);

}

document.onmousedown = block;

</script>

 

第二種方式:

<script language=”javascript”>

function block(oEvent){

    if(window.event){

        oEvent = window.event;

        oEvent.returnValue = false;    //取消默認事件支持IE

    }else

        oEvent.preventDefault();    //取消默認事件支持Firefox

}

document.oncontextmenu = block;

</script>

6.8伸縮的菜單

<script language=”javascript”>

function change(){

    //通過父元素li,找到兄弟元素ul

    var oSecondDiv = this.parentNode.getElementsByTagName(“ul”)[0];//這裏的this就是下面的OA

    //CSS交替更換來實現顯、隱

    if(oSecondDiv.className == “myHide”)

        oSecondDiv.className = “myShow”;

    else

        oSecondDiv.className = “myHide”;

}

window.onload = function(){

    var oUl = document.getElementById(“listUL”);

    var aLi = oUl.childNodes;    //子元素

    var oA;

    for(var i=0;i<aLi.length;i++){

        //如果子元素爲li,且這個li有子菜單ul

        if(aLi[i].tagName == “LI”&& aLi[i].getElementsByTagName(“ul”).length){

            oA = aLi[i].firstChild;    //找到超鏈接

            oA.onclick = change;    //動態添加點擊函數

        }

    }

}

</script>

 

tagName出來的都是大寫

總結

《Event詳解》

DOM常用屬性

tagName

nodeValue

nodeName

nodeType

parentNode

childNodes

firstChild

lastChild

nextSibling (IE)

previousSibling (IE)

attributes

innerHTML

style

className

 

方法

getElementById

getElementsByName

getElementsByTagName

hasChildNodes()

getAttribute

setAttribute

createElement

createTextNode

appendChild

removeChild

replaceChild

insertBefore

cloneNode

createDocumentFragment

detachEvent

attachEvent(IE) addEventListener(DOM)

 

event屬性

type

keyCode

srcElement(IE) target(DOM)

button

 

 

鼠標事件

onclick

onmouseover

onmousedown

onmouseup

onmouseout

ondblclick

 

 

鍵盤事件

onkeydown

onkeyup

onkeypress

 

window事件

onload

 

document事件

oncontextmenu

write

onmousedown

7.JavaScipt優化和調試

7.1 錯誤和異常

拼寫錯誤、訪問不存在的變量,括號不匹配,等號與賦值

 

聲明變量時,要記住局部變量和全局變量的區別

 

Function square(num){

    Total = num*num;

Return total;

}

Var total = 50;

Var number = Square(20);

Alert(total);

 

這些代碼將不可避免地導致全局變量total的值發生變化。

Function square(num){

    Var Total = num*num;

Return total;

}

7.2 錯誤處理

 

onerror

<head>

<title>onerror</title>

<script language=”javascript”>

window.onerror = function(){

    alert(“出錯啦!”);

    return true;    //屏蔽系統事件

}

</script>

</head>

<body onload=”nonExistent()”>

</body>

 

Try..catch

<script language=”javascript”>

try{

    alert(“this is an example”);

    alert(fresheggs);

} catch(exception){

    var sError = “”;

    for(var i in exception)

        sError += i + “:” + exception[i] + “\n”;

    alert(sError);

}

</script>

7.3 調試器

IE-工具-Intenet選項-高級->禁用調試,顯示腳本錯誤

 

Firefox錯誤控制檯

Microsoft script debugger

Venkman firefox的插件

 

 

6.4 JavaScript優化

1.提高JavaScript下載時間。將JavaScript寫到同一行

2.儘量使用內置函數(因爲內置函數是通過C語言編譯到瀏覽器中的)

.實例

1 圖片查看器

<html>

<head>

    <title></title>

    <script>

        

        function showPic(obj){

                var h = obj.getAttribute(“href”);        

                document.getElementById(“image”).setAttribute(“src”,h);

        }

    </script>

</head>

<body>

<h1>Snapshots</h1>

<ul>

    <li><a href=”photo/01.jpg” title=”a” onclick=”showPic(this);return false;“>01</a></li>

    <li><a href=”photo/02.jpg” title=”b” onclick=”showPic(this);return false;”>02</a></li>

    <li><a href=”photo/03.jpg” title=”c” onclick=”showPic(this);return false;”>03</a></li>

    <li><a href=”photo/04.jpg” title=”d” onclick=”showPic(this);return false;”>04</a></li>

    <li><a href=”photo/05.jpg” title=”e” onclick=”showPic(this);return false;”>05</a></li>

</ul>

<img id=”image” src=”photo/01.jpg” alt=”my image”></img>

</body>

</html>

Return false指的是把默認的noclick事件取消

給其加上css

<style>

    body{

        color:#333;

        background:#ccc;

        margin:1em 10%;

    }

    a{

        text-decoration:none;

        padding:10px;

        color:#c60;

    }

    a:link, a:visited{

        color: #A62020; background-color: #ecd8db; text-decoration: none; padding:4px 10px 4px 10px;

        border-top:1px solid #EEE;

        border-left:1px solid #EEE;

        border-bottom:1px solid #717171;

        border-right:1px solid #717171;

        

    }

    a:hover{

        color:#821818; background-color:#e2c4c9; padding:5px 8px 3px 12px;

        border-top:1px solid #717171;

        border-left:1px solid #717171;

        border-bottom:1px solid #EEE;

        border-right:1px solid #EEE;}

    ul{

        margin:0px;

        padding:0px;

    }

    li{

        list-style-type:none;

        display:inline;

    }

    img{

        margin:10px 0px;

    }

    </style>

當時現在有個缺陷,就是onclick的事件直接寫在了HTML上,分離

先給ul加上個屬性id<ul id=”img_ul”>

window.onload = prepareGalley;

        function prepareGalley(){

            var img_ul = document.getElementById(“img_ul”);

            var links = img_ul.getElementsByTagName(“a”);

 

            for(var i=0;i<links.length;i++){

                links[i].onclick = function(){

                    showPic(this);

                    return false;

                }

            }

        }

 

 

有一個問題,如果onload的函數有多個怎麼辦?

window.onload = prepareGalley1;

window.onload = prepareGalley2;

顯然,這樣第一個函數就會被第二個函數覆蓋。

 

可以這樣寫

 

Window.onload = function(){

    prepareGalley1();

    prepareGalley2();

}

 

還有一個比這個更NB的寫法,由Simon Willison寫的

function addLoadEvent(func){

            var oldonload = window.onload;

            if(typeof window.onload !=’function’){

                window.onload = func;

            }else{

                window.onload = function(){

                    oldonload();

                    func();

                }

            }

        }

        

    addLoadEvent(prepareGalley1);

    addLoadEvent(prepareGalley2);

 

編寫一個方法求一個字符串的字節長度

new function(s){

        if(!arguments.length||!s) return null;     

    if(“”==s) return 0;     

    var l=0;

        for(var i=0;i<s.length;i++){         

        if(s.charCodeAt(i)>255) l+=2; else l++;     

    }     

    alert(l);

}(“hello world!”);

 

如何控制alert中的換行

alert(“hello\nworld”);

 

解釋document.getElementById(“ElementID”).style.fontSize=”1.5em”

設置id爲ElementID的元素的字體大小爲1.5個相對單位

Em爲相對長度單位。相對於當前對象內文本的字體尺寸。

如當前對行內文本的字體尺寸未被人爲設置,則相對於瀏覽器的默認字體尺寸。

    1em=16px

 

按照格式 xxxx年xx月xx日xx時xx分xx秒動態顯示時間要求不足10的補0

<script type=”text/javascript” language=”javascript”>    

function tick(){

var d=new Date();

var t=function(a){return a<10?”0″+a:a;}

Clock.innerHTML=d.getFullYear()+”年”+t(d.getMonth()+1)+”月”+t(d.getDate())+”日”+t(d.getHours())+”時”

+t(d.getMinutes())+”分”+t(d.getSeconds())+”秒”;

window.setTimeout(“tick()”,1000);

}

window.onload=tick;

</script>

 

<body>

<div id=”Clock”></div>

</body>

 

編寫一個方法去掉一個數組的重複元素

    Array.prototype.strip=function(){     

if(this.length<2) return [this[0]]||[];     

var arr=[];     

for(var i=0;i<this.length;i++){         

arr.push(this.splice(i–,1));//將本數組中第一個元素取出放入到數組arr中        

for(var j=0;j<this.length;j++){             

if(this[j]==arr[arr.length-1]){                 

this.splice(j–,1);//刪除本數組中與數組arr中最後一個元素相同的元素

}         

}     

}

return arr;

}

 

var arr=["abc",85,"abc",85,8,8,1,2,5,4,7,8];

alert(arr.strip());

 

說出3條以上ff和ie的腳本兼容問題

IE有children,FF沒有;

IE有parentElement,FF沒有;

IE有 innerText,outerText,outerHTML,FF沒有;

IE有數據島,FF沒有;

FF有

HTMLElement,HTMLDivElement,XMLDocument,DocumentFragment,Node,Event,Element 等等,IE沒有;

IE跟FF創建HttpRequest實例的方法不一樣

 

DIV中border、margin和padding的區別和用法

邊框屬性(border)用來設定一個元素的邊線

外邊距屬性(margin)是用來設置一個元素所佔空間的邊緣到相鄰元素之間的距離

內邊距屬性(padding)是用來設置元素內容到元素邊界的距離

 

爲Array寫一個indexof方法

Array.prototype.indexOf = function(e){

for(var i=0,j; j=this[i]; i++){

if(j==e){return i;}

}

return -1;

}

 

Array.prototype.lastIndexOf = function(e){

for(var i=this.length-1,j; j=this[i]; i–){

if(j==e){return i;}

}

return -1;

}

 

var arr=[1,2,3,4,5];

alert(arr.indexOf(5));

 

克隆

淺複製(影子克隆):只複製對象的基本類型,對象類型,仍屬於原來的引用

深複製(深度克隆):不緊複製對象的基本類,同時也複製原對象中的對象.就是說完全是新對象產生的

 

Object.prototype.Clone = function(){

    var objClone;

    if( this.constructor == Object )

objClone = new this.constructor();

    else

objClone = new this.constructor(this.valueOf());

    for ( var key in this ){

    if ( objClone[key] != this[key] ){

    if ( typeof(this[key]) == ‘object’ ){

    objClone[key] = this[key].Clone();

    }else{

    objClone[key] = this[key];

    }

    }

    }

    objClone.toString = this.toString;

    objClone.valueOf = this.valueOf;

    return objClone;

    }

 

兼容 IE 和 FF 的換行 CSS 推薦樣式

word-wrap:break-word; overflow:hidden;

 

word-wrap是控制換行的。使用break-word時,是將強制換行。中文沒有任何問題,英文語句也沒問題。但是對於長串的英文,就不起作用。

 

word-break是控制是否斷詞的。

normal是默認情況,英文單詞不被拆開。

break-all,是斷開單詞。在單詞到邊界時,下個字母自動到下一行。主要解決了長串英文的問題。

keep-all,是指Chinese, Japanese, and Korean不斷詞。即只用此時,不用word-wrap,中文就不會換行了。(英文語句正常。)

 

手型Cursor的兼容IE和FF寫法

cursor:pointer

 

<img>元素的alt和title有什麼異同?

alt作爲圖片的替代文字出現,title是圖片的解釋文字

 

圖片存在

只有alt 圖片的解釋文字

只有title 圖片的解釋文字

兩者都有圖片的解釋文字

兩者都沒有圖片既沒有替代文字,也沒有解釋文字

 

圖片不存在

只有alt 圖片既有替代文字,又有解釋文字

只有title 圖片沒有替代文字,只有解釋文字

兩者都有圖片既有替代文字,又有解釋文字

兩者都沒有圖片既沒有替代文字,也沒有解釋文字

 

當然不同的瀏覽器處理方式也會不一樣

 

border-color-left、marin-left、-moz-viewport改寫成JavaScript格式

border-color-left:borderLeftColor

marin-left:marinLeft

-moz-viewport:MozViewport

 

用css、html編寫一個兩列布局的網頁,要求右側寬度爲200px,左側自動擴展。

CSS:

#right{

    float:right;

    width:200px;

}

#left{

    marin-right:200px;

}

HTML:

<body>

    <div id=”right”>…</div>

    <div id=”left”>…</div>

</body>

 

Linux題目:批量刪除當前目錄下後綴名爲.c的文件,如a.c、b.c

rm *.c

 

如何提高網頁的運行速度

內容與形式分離,模塊化開發,優化CSS

減少頁面文檔大小

儘量減少圖片的使用或注意圖片的大小,優化圖片:格式、質量、圖片長寬標誌

減少響應的次數,用Ajax

網址後面加一個”/”

 

按要求寫一個簡單的ajax示例

<body>

<div id=”load”>數據正在加載……</div>

<script type=”text/javascript”>

var Browser={/**Browser對象用於檢測瀏覽器,其中用到了IE的條件編譯*/

isFF:window.navigator.appName.toUpperCase().indexOf(“NETSCAPE”)!=-1?true:false,     

isOpera:window.navigator.appName.toUpperCase().indexOf(“OPERA”)!=-1?true:false

};

 

Function.prototype.bind=function(object){     

var _this=this;     

return function(){         

_this.apply(object,arguments);     

}

}

 

function HttpRequest(){     

this.async=true;     

this.cache=false;     

this.xmlhttp=function(){         

if(Browser.isFF&&window.XMLHttpRequest){             

try{                

return new XMLHttpRequest();

}catch(e){}         

}else if(Browser.isIE&&window.ActiveXObject){             

var Version = ["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.5.0","Msxml2.XMLHTTP.4.0","Msxml2.XMLHTTP.3.0",+

"Msxml2.XMLHTTP.2.6","Msxml2.XMLHTTP","Microsoft.XMLHTTP.1.0","Microsoft.XMLHTTP.1","Microsoft.XMLHTTP"];             

for(var i=0;i<Version.length;i++){                 

try{                    

return new ActiveXObject(Version[i]);                 

}catch(e){}             

}         

}     

}()||false;

}HttpRequest.prototype={

send:function(object,url,callback){         

if(!this.xmlhttp) return;         

this.xmlhttp.open(object?”post”:”get”,url,!!this.async);

if(object) this.xmlhttp.setRequestHeader(“content-type”,”application/x-www-form-urlencoded”);         

if(!this.cache){             

this.xmlhttp.setRequestHeader(“No-Cache”,”1″);             

this.xmlhttp.setRequestHeader(“Pragma”,”no-cache”);             

this.xmlhttp.setRequestHeader(“Cache-Control”,”no-cache”);

this.xmlhttp.setRequestHeader(“Expire”,”0″);             

this.xmlhttp.setRequestHeader(“Last-Modified”,”Wed, 1 Jan 1997 00:00:00 GMT”);             

this.xmlhttp.setRequestHeader(“If-Modified-Since”,”-1″);

}         

if(!this.callback) this.callback=callback;         

if(!this.async){             

if(typeof(this.callback)==”string”){                 

eval(this.callback);             

}else if(typeof(this.callback)==”function”){                 

this.callback(this.xmlhttp);

}         

}else{             

this.xmlhttp.onreadystatechange=function(){                 

if(this.xmlhttp.readyState==4){                     

if(this.xmlhttp.status==0||this.xmlhttp.status==200){                         

if(typeof(this.callback)==”string”){                             

eval(this.callback);                         

}elseif(typeof(this.callback)==”function”){                             

this.callback(this.xmlhttp);                         

}                     

}                 

}             

}.bind(this);         

}         

this.xmlhttp.send(object);     

},abort:function(){         

if(this.xmlhttp&&this.xmlhttp.abort) this.xmlhttp.abort();     

}

}; //ajax類定義結束

new HttpRequest().send(null,”http://bbs.51js.com/index.php”,function(r){

document.getElementById(“load”).innerHTML=r.responseText.match(/<img.*?(?:\/)?>/img).join(“”); });

</script>

</body>

 

 

 

IE6、IE7、IE8、Firefox兼容性CSS HACK代碼+示例

________________________________________

整理關於IE6、IE7、IE8、Firefox兼容性CSS HACK問題

1.區別IE和非IE瀏覽器CSS HACK代碼

#divcss5{

background:blue; /*非IE 背景藍色*/

background:red \9; /*IE6、IE7、IE8背景紅色*/

}

2.區別IE6,IE7,IE8,FF CSS HACK

【區別符號】:「\9」、「*」、「_」

【示例】:

#divcss5{

background:blue; /*Firefox 背景變藍色*/

background:red \9; /*IE8 背景變紅色*/

*background:black; /*IE7 背景變黑色*/

_background:orange; /*IE6 背景變橘色*/

}

 

【說明】:因爲IE系列瀏覽器可讀「\9」,而IE6和IE7可讀「*」(米字號),另外IE6可辨識「_」(底線),因此可以依照順序寫下來,就會讓瀏覽器正確的讀取到自己看得懂得CSS語法,所以就可以有效區分IE各版本和非IE瀏覽器(像是Firefox、Opera、Google Chrome、Safari等)。

3.區別IE6、IE7、Firefox (EXP 1)

【區別符號】:「*」、「_」

【示例】:

#divcss5{

background:blue; /*Firefox背景變藍色*/

*background:black; /*IE7 背景變黑色*/

_background:orange; /*IE6 背景變橘色*/

}

 

【說明】:IE7和IE6可讀「*」(米字號),IE6又可以讀「_」(底線),但是IE7卻無法讀取「_」,至於Firefox(非IE瀏覽器)則完全無法辨識「*」和「_」,因此就可以透過這樣的差異性來區分IE6、IE7、Firefox

4.區別IE6、IE7、Firefox (EXP 2)

【區別符號】:「*」、「!important」

【示例】:

#divcss5{

background:blue; /*Firefox 背景變藍色*/

*background:green !important; /*IE7 背景變綠色*/

*background:orange; /*IE6 背景變橘色*/

}

 

【說明】:IE7可以辨識「*」和「!important」,但是IE6只可以辨識「*」,卻無法辨識「!important」,至於Firefox可以讀取「!important」但不能辨識「*」因此可以透過這樣的差異來有效區隔IE6、IE7、Firefox。

5.區別IE7、Firefox

【區別符號】:「*」、「!important」

【示例】:

#divcss5{

background:blue; /*Firefox 背景變藍色*/

*background:green !important; /*IE7 背景變綠色*/

}

 

【說明】:因爲Firefox可以辨識「!important」但卻無法辨識「*」,而IE7則可以同時看懂「*」、「!important」,因此可以兩個辨識符號來區隔IE7和Firefox。

6.區別IE6、IE7 (EXP 1)

【區別符號】:「*」、「_」

【示例】:

#tip {

*background:black; /*IE7 背景變黑色*/

_background:orange; /*IE6 背景變橘色*/

}

 

【說明】:IE7和IE6都可以辨識「*」(米字號),但IE6可以辨識「_」(底線),IE7卻無法辨識,透過IE7無法讀取「_」的特性就能輕鬆區隔IE6和IE7之間的差異。

7.區別IE6、IE7 (EXP 2)

【區別符號】:「!important」

【示例】:

#divcss5{

background:black !important; /*IE7 背景變黑色*/

background:orange; /*IE6 背景變橘色*/

}

【說明】:因爲IE7可讀取「!important;」但IE6卻不行,而CSS的讀取步驟是從上到下,因此IE6讀取時因無法辨識「!important」而直接跳到下一行讀取CSS,所以背景色會呈現橘色。

8.區別IE6、Firefox

【區別符號】:「_」

【示例】:

#divcss5{

background:black; /*Firefox 背景變黑色*/

 

_background:orange; /*IE6 背景變橘色*/

}

【說明】:因爲IE6可以辨識「_」(底線),但是Firefox卻不行,因此可以透過這樣的差異來區隔Firefox和IE6,有效達成CSS hack。

以上包括了IE6\IE8\IE7\火狐瀏覽器兼容問題及解決方法。

 

[HTML&& CSS]

1. Doctype? 嚴格模式與混雜模式-如何觸發這兩種模式,區分它們有何意義?

Doctype聲明位於文檔中的最前面的位置,處於標籤之前。此標籤可告知瀏覽器文檔使用哪種 HTML 或 XHTML 規範。該標籤可聲明三種DTD 類型,分別表示嚴格版本、過渡版本以及基於框架的 HTML 文檔。

當瀏覽器廠商開始創建與標準兼容的瀏覽器時,他們希望確保向後兼容性。爲了實現這一點,他們創建了兩種呈現模式:標準模式和混雜模式(quirks mode)。在標準模式中,瀏覽器根據規範呈現頁面;在混雜模式中,頁面以一種比較寬鬆的向後兼容的方式顯示。混雜模式通常模擬老式瀏覽器(比如Microsoft IE 4和Netscape Navigator 4)的行爲以防止老站點無法工作。

瀏覽器根據DOCTYPE是否存在以及使用的哪種DTD來選擇要使用的呈現方法。如果XHTML文檔包含形式完整的DOCTYPE,那麼它一般以標準模式呈現。對於HTML 4.01文檔,包含嚴格DTD的DOCTYPE常常導致頁面以標準模式呈現。包含過渡DTD和URI的DOCTYPE也導致頁面以標準模式呈現,但是有過渡DTD而沒有URI會導致頁面以混雜模式呈現。DOCTYPE不存在或形式不正確會導致HTML和XHTML文檔以混雜模式呈現。

2. 行內元素有哪些?塊級元素有哪些?CSS的盒模型?

行內元素有:a b span I bem img input select strong

塊級元素有:div ul ol lidl dt dd h1 h2 h3 h4…p

盒模型:margin borderpadding width

3. CSS引入的方式有哪些? link和@import的區別是?

1. 使用 LINK標籤

將樣式規則寫在.css的樣式文件中,再以<link>標籤引入。

<link rel=stylesheet type=”text/css” href=”example.css”>

2. 使用@import引入

跟link方法很像,但必須放在<STYLE>…</STYLE>中

<STYLE TYPE=”text/css”>

<!–

@import url(css/example.css);

–>

</STYLE>

3. 使用STYLE標籤

將樣式規則寫在<STYLE>…</STYLE>標籤之中。

<STYLE TYPE=”text/css”>

<!–

body {color: #666;background: #f0f0f0;font-size: 12px;}

td,p {color:#c00;font-size: 12px;}

–>

</STYLE>

4. 使用STYLE屬性

將STYLE屬性直接加在個別的元件標籤裏,<元件(標籤) STYLE=”性質(屬性)1: 設定值1; 性質(屬性)2: 設定值2; …}

5. 使用<span></span>標記引入樣式

<span style=”font:12px/20px #000000;”>cnwebshow.com</span>

 

兩者區別:加載順序的差別。當一個頁面被加載的時候,link引用的CSS會同時被加載,而@import引用的CSS會等到頁面全部被下載完再被加載。@import可以在css中再次引入其他樣式表,比如可以創建一個主樣式表,在主樣式表中再引入其他的樣式表,如:

 

main.css

———————-

@import”sub1.css”;

@import”sub2.css”;

這樣做有一個缺點,會對網站服務器產生過多的HTTP請求,以前是一個文件,而現在卻是兩個或更多文件了,服務器的壓力增大,瀏覽量大的網站還是謹慎使用。

 

4. CSS選擇符有哪些?哪些屬性可以繼承?優先級算法如何計算?內聯和important哪個優先級高?

通配選擇符* { sRules }

類型選擇符E { sRules }

td { font-size:14px; width:120px; }

屬性選擇符

E [ attr ] { sRules }

E [ attr = value ] { sRules }

E [ attr ~= value ] { sRules }

E [ attr |= value ] { sRules }

h[title] { color: blue; }/* 所有具有title屬性的h對象 */

span[class=demo] { color: red; }

div[speed="fast"][dorun="no"] { color: red; }

a[rel~="copyright"] { color:black; }

包含選擇符E1 E2 { sRules }

table td { font-size:14px; }

子對象選擇符E1 > E2 { sRules }

div ul>li p { font-size:14px; }

ID選擇符#ID { sRules }

類選擇符E.className { sRules }

選擇符分組

E1 , E2 , E3 { sRules }

僞類及僞對象選擇符

E : Pseudo-Classes { sRules }

( Pseudo-Classes )[:link :hover :active :visited :focus :first-child :first :left :right :lang]

E : Pseudo-Elements { sRules }

( Pseudo-Elements )[:first-letter :first-line :before :after]

可以繼承的有:font-size font-family color

不可繼承的一般有:border padding margin background-color width height等

============================

關於CSS specificity

CSS 的specificity 特性或稱非凡性,它是衡量一個衡量CSS值優先級的一個標準,既然作爲標準,就具有一套相關的判定規定及計算方式,specificity用一個四位的數字串(CSS2是三位)來表示,更像四個級別,值從左到右,左面的最大,一級大於一級,數位之間沒有進制,級別之間不可超越。

在多個選擇符應用於同一個元素上那麼Specificity值高的最終獲得優先級。

使用!important可以改變優先級別爲最高,其次是style對象,然後是id> class >tag ,另外在同級樣式按照申明的順序後出現的樣式具有高優先級。

5. 前端頁面由哪三層構成,分別是什麼?作用是什麼?

網頁分成三個層次,即:結構層、表示層、行爲層。

網頁的結構層(structurallayer)由HTML 或XHTML 之類的標記語言負責創建。標籤,也就是那些出現在尖括號裏的單詞,對網頁內容的語義含義做出了描述,但這些標籤不包含任何關於如何顯示有關內容的信息。例如,P標籤表達了這樣一種語義:”這是一個文本段。”

網頁的表示層(presentationlayer)由CSS 負責創建。CSS 對”如何顯示有關內容”的問題做出了回答。

網頁的行爲層(behaviorlayer)負責回答”內容應該如何對事件做出反應”這一問題。這是Javascript 語言和DOM 主宰的領域。

6. css的基本語句構成是?

選擇器{屬性1:值1;屬性2:值2;……}

7. 你做的頁面在哪些流覽器測試過?這些瀏覽器的內核分別是什麼?經常遇到的瀏覽器的兼容性有哪些?怎麼會出現?解決方法是什麼?

IE內核瀏覽器:360,傲遊,搜狗,世界之窗,騰訊TT

非IE內核瀏覽器:firefoxopera safari chrome

8. 如何居中一個浮動元素?

設置容器的浮動方式爲相對定位,然後確定容器的寬高,比如寬500 高 300 的層,然後設置層的外邊距。

div{Width:500px;height:300px;Margin: -150px 0 0-250px;position:relative;left:50%;top:50%;}

9. 有沒有關注HTML5和CSS3?如有請簡單說一些您對它們的瞭解情況!

HTML5標籤的改變:<header>,<footer>, <dialog>, <aside>, <figure>, <section>等

IE9以上開始支持

CSS3實現圓角,陰影,對文字加特效,增加了更多的CSS選擇器。

10. 如果讓你來製作一個訪問量很高的大型網站,你會如何來管理所有CSS文件、JS與圖片?

11. 你對前端界面工程師這個職位是怎麼樣理解的?它的前景會怎麼樣?

以下爲Web前端開發筆試題集錦之Javascript篇,移步HTML/CSS篇

1, 判斷字符串是否是這樣組成的,第一個必須是字母,後面可以是字母、數字、下劃線,總長度爲5-20

var reg = /^[a-zA-Z][a-zA-Z_0-9]{4,19}$/;

reg.test(“a1a__a1a__a1a__a1a__”);

2,截取字符串abcdefg的efg

var str = “abcdefg”;

if (/efg/.test(str)) {

var efg = str.substr(str.indexOf(“efg”), 3);

alert(efg);

}

3,判斷一個字符串中出現次數最多的字符,統計這個次數

//將字符串的字符保存在一個hash table中,key是字符,value是這個字符出現的次數

var str = “abcdefgaddda”;

var obj = {};

for (var i = 0, l = str.length; i &lt; l; i++) {

var key = str[i];

if (!obj[key]) {

obj[key] = 1;

} else {

obj[key]++;

}

}

 

/*遍歷這個hash table,獲取value最大的key和value*/

var max = -1;

var max_key = “”;

var key;

for (key in obj) {

if (max < obj[key]) {

max = obj[key];

max_key = key;

}

}

 

alert(“max:”+max+” max_key:”+max_key);

4,IE與FF腳本兼容性問題

(1) window.event:

表示當前的事件對象,IE有這個對象,FF沒有,FF通過給事件處理函數傳遞事件對象

(2) 獲取事件源

IE用srcElement獲取事件源,而FF用target獲取事件源

(3) 添加,去除事件

IE:element.attachEvent(“onclick”, function) element.detachEvent(“onclick”, function)

FF:element.addEventListener(“click”, function, true) element.removeEventListener(“click”, function, true)

(4) 獲取標籤的自定義屬性

IE:div1.value或div1["value"]

FF:可用div1.getAttribute(“value”)

(5) document.getElementByName()和document.all[name]

IE;document.getElementByName()和document.all[name]均不能獲取div元素

FF:可以

(6) input.type的屬性

IE:input.type只讀

FF:input.type可讀寫

(7) innerText textContent outerHTML

IE:支持innerText, outerHTML

FF:支持textContent

(8) 是否可用id代替HTML元素

IE:可以用id來代替HTML元素

FF:不可以

這裏只列出了常見的,還有不少,更多的介紹可以參看JavaScript在IE瀏覽器和Firefox瀏覽器中的差異總結

5,規避javascript多人開發函數重名問題

(1) 可以開發前規定命名規範,根據不同開發人員開發的功能在函數前加前綴

(2) 將每個開發人員的函數封裝到類中,調用的時候就調用類的函數,即使函數重名只要類名不重複就ok

6,javascript面向對象中繼承實現

javascript面向對象中的繼承實現一般都使用到了構造函數和Prototype原型鏈,簡單的代碼如下:

function Animal(name) {

this.name = name;

}

 

Animal.prototype.getName = function() {alert(this.name)}

function Dog() {};

Dog.prototype = new Animal(“Buddy”);

Dog.prototype.constructor = Dog;

var dog = new Dog();

7,FF下面實現outerHTML

FF不支持outerHTML,要實現outerHTML還需要特殊處理

思路如下:

在頁面中添加一個新的元素A,克隆一份需要獲取outerHTML的元素,將這個元素append到新的A中,然後獲取A的innerHTML就可以了。

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml”>

<head>

<meta http-equiv=”Content-Type” content=”text/html; charset=gb2312″ />

<title>獲取outerHMTL</title>

<style>

div{ background:#0000FF;width:100px;height:100px;}

span{ background:#00FF00;width:100px;height:100px;}

p{ background:#FF0000;width:100px;height:100px;}

</style>

</head>

<body>

<div id=”a”><span>SPAN</span>DIV</div>

<span>SPAN</span>

<p>P</p>

<script type=”text/javascript”>

function getOuterHTML(id){

var el = document.getElementById(id);

var newNode = document.createElement(“div”);

document.appendChild(newNode);

var clone = el.cloneNode(true);

newNode.appendChild(clone);

alert(newNode.innerHTML);

document.removeChild(newNode);

}

getOuterHTML(“a”);

</script>

</body>

</html>

8,編寫一個方法求一個字符串的字節長度

假設:

一個英文字符佔用一個字節,一箇中文字符佔用兩個字節

function GetBytes(str){

var len = str.length;

var bytes = len;

for(var i=0; i<len; i++){

if (str.charCodeAt(i) > 255) bytes++;

}

return bytes;

}

alert(GetBytes(“你好,as”));

9,編寫一個方法去掉一個數組的重複元素

var arr = [1 ,1 ,2, 3, 3, 2, 1];

Array.prototype.unique = function(){

var ret = [];

var o = {};

var len = this.length;

for (var i=0; i<len; i++){

var v = this[i];

if (!o[v]){

o[v] = 1;

ret.push(v);

}

}

return ret;

};

alert(arr.unique());

10,寫出3個使用this的典型應用

(1)在html元素事件屬性中使用,如

<input type=”button” onclick=”showInfo(this);” value=”點擊一下”/>

(2)構造函數

function Animal(name, color) {

this.name = name;

this.color = color;

}

(3)

<input type=”button” id=”text” value=”點擊一下” />

<script type=”text/javascript”>

var btn = document.getElementById(“text”);

btn.onclick = function() {

alert(this.value); //此處的this是按鈕元素

}

</script>

(4)CSS expression表達式中使用this關鍵字

<table width=”100px” height=”100px”>

<tr>

<td>

<div style=”width:expression(this.parentNode.width);”>div element</div>

</td>

</tr>

</table>

12,如何顯示/隱藏一個DOM元素?

el.style.display = “”;

el.style.display = “none”;

el是要操作的DOM元素

13,JavaScript中如何檢測一個變量是一個String類型?請寫出函數實現

String類型有兩種生成方式:

(1)Var str = “hello world”;

(2)Var str2 = new String(“hello world”);

function IsString(str){

return (typeof str == “string” || str.constructor == String);

}

var str = “”;

alert(IsString(1));

alert(IsString(str));

alert(IsString(new String(str)));

14,網頁中實現一個計算當年還剩多少時間的倒數計時程序,要求網頁上實時動態顯示”××年還剩××天××時××分××秒”

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN” “http://www.w3.org/TR/html4/loose.dtd”>

<html>

<head>

<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″>

<title>倒計時</title>

</head>

<body>

<input type=”text” value=”” id=”input” size=”1000″/>

<script type=”text/javascript”>

function counter() {

var date = new Date();

var year = date.getFullYear();

var date2 = new Date(year, 12, 31, 23, 59, 59);

var time = (date2 – date)/1000;

var day =Math.floor(time/(24*60*60))

var hour = Math.floor(time%(24*60*60)/(60*60))

var minute = Math.floor(time%(24*60*60)%(60*60)/60);

var second = Math.floor(time%(24*60*60)%(60*60)%60);

var str = year + “年還剩”+day+”天”+hour+”時”+minute+”分”+second+”秒”;

document.getElementById(“input”).value = str;

}

window.setInterval(“counter()”, 1000);

</script>

</body>

</html>

15,補充代碼,鼠標單擊Button1後將Button1移動到Button2的後面<div><input type=”button” id =”button1″ value=”1″ onclick=”???”><input type=”button” id =”button2″ value=”2″ /”></div>

<div>

<input type=”button” id =”button1″ value=”1″ onclick=”moveBtn(this);”>

<input type=”button” id =”button2″ value=”2″ />

</div>

<script type=”text/javascript”>

function moveBtn(obj) {

var clone = obj.cloneNode(true);

var parent = obj.parentNode;

parent.appendChild(clone);

parent.removeChild(obj);

}

</script>

16,JavaScript有哪幾種數據類型

簡單:Number,Boolean,String,Null,Undefined

複合:Object,Array,Function

17,下面css標籤在JavaScript中調用應如何拼寫,border-left-color,-moz-viewport

borderLeftColor

mozViewport

18,JavaScript中如何對一個對象進行深度clone

function cloneObject(o) {

if(!o || ‘object’ !== typeof o) {

return o;

}

var c = ‘function’ === typeof o.pop ? [] : {};

var p, v;

for(p in o) {

if(o.hasOwnProperty(p)) {

v = o[p];

if(v && ‘object’ === typeof v) {

c[p] = Ext.ux.clone(v);

}

else {

c[p] = v;

}

}

}

return c;

};

19,如何控制alert中的換行

\n alert(“p\np”);

20,請實現,鼠標點擊頁面中的任意標籤,alert該標籤的名稱.(注意兼容性)

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml”>

<head>

<meta http-equiv=”Content-Type” content=”text/html; charset=gb2312″ />

<title>鼠標點擊頁面中的任意標籤,alert該標籤的名稱</title>

<style>

div{ background:#0000FF;width:100px;height:100px;}

span{ background:#00FF00;width:100px;height:100px;}

p{ background:#FF0000;width:100px;height:100px;}

</style>

<script type=”text/javascript”>

document.onclick = function(evt){

var e = window.event || evt;

var tag = e["target"] || e["srcElement"];

alert(tag.tagName);

};

</script>

</head>

<body>

<div id=”div”><span>SPAN</span>DIV</div>

<span>SPAN</span>

<p>P</p>

</body>

</html>

21,請編寫一個JavaScript函數 parseQueryString,它的用途是把URL參數解析爲一個對象,如:

var url = “http://witmax.cn/index.php?key0=0&key1=1&key2=2″;

 

function parseQueryString(url){

var params = {};

var arr = url.split(“?”);

if (arr.length <= 1)

return params;

arr = arr[1].split(“&”);

for(var i=0, l=arr.length; i<l; i++){

var a = arr[i].split(“=”);

params[a[0]] = a[1];

}

return params;

}

 

var url = “http://witmax.cn/index.php?key0=0&key1=1&key2=2″;

var ps = parseQueryString(url);

alert(ps["key1"]);

22,ajax是什麼? ajax的交互模型? 同步和異步的區別? 如何解決跨域問題?

Ajax是多種技術組合起來的一種瀏覽器和服務器交互技術,基本思想是允許一個互聯網瀏覽器向一個遠程頁面/服務做異步的http調用,並且用收到的數據來更新一個當前web頁面而不必刷新整個頁面。該技術能夠改進客戶端的體驗。包含的技術:

XHTML:對應W3C的XHTML規範,目前是XHTML1.0。

CSS:對應W3C的CSS規範,目前是CSS2.0

DOM:這裏的DOM主要是指HTML DOM,XML DOM包括在下面的XML中

JavaScript:對應於ECMA的ECMAScript規範

XML:對應W3C的XML DOM、XSLT、XPath等等規範

XMLHttpRequest:對應WhatWG的Web Applications1.0規範(http://whatwg.org/specs/web-apps/current-work/)

AJAX交互模型

 

同步:腳本會停留並等待服務器發送回覆然後再繼續

異步:腳本允許頁面繼續其進程並處理可能的回覆

跨域問題簡單的理解就是因爲JS同源策略的限制,a.com域名下的JS無法操作b.com或c.a.com下的對象,具體場景如下:

 

PS:(1)如果是端口或者協議造成的跨域問題前端是無能爲力的

(2) 在跨域問題上,域僅僅通過URL的首部來識別而不會嘗試判斷相同的IP地址對應的域或者兩個域是否對應一個IP

前端對於跨域的解決辦法:

(1) document.domain+iframe

(2) 動態創建script標籤

23,什麼是閉包?下面這個ul,如何點擊每一列的時候alert其index?

<ul id=”test”>

<li>這是第一條</li>

<li>這是第二條</li>

<li>這是第三條</li>

</ul>

內部函數被定義它的函數的外部區域調用的時候就產生了閉包。

(function A() {

var index = 0;

var ul = document.getElementById(“test”);

var obj = {};

for (var i = 0, l = ul.childNodes.length; i < l; i++) {

if (ul.childNodes[i].nodeName.toLowerCase() == “li”) {

var li = ul.childNodes[i];

li.onclick = function() {

index++;

alert(index);

}

}

}

})();

24,請給出異步加載js方案,不少於兩種

默認情況javascript是同步加載的,也就是javascript的加載時阻塞的,後面的元素要等待javascript加載完畢後才能進行再加載,對於一些意義不是很大的javascript,如果放在頁頭會導致加載很慢的話,是會嚴重影響用戶體驗的。

異步加載方式:

(1) defer,只支持IE

(2) async:

(3) 創建script,插入到DOM中,加載完畢後callBack,見代碼:

function loadScript(url, callback){

var script = document.createElement(“script”)

script.type = “text/javascript”;

if (script.readyState){ //IE

script.onreadystatechange = function(){

if (script.readyState == “loaded” ||

script.readyState == “complete”){

script.onreadystatechange = null;

callback();

}

};

} else { //Others: Firefox, Safari, Chrome, and Opera

script.onload = function(){

callback();

};

}

script.src = url;

document.body.appendChild(script);

}

25,請設計一套方案,用於確保頁面中JS加載完全。

var n = document.createElement(“script”);

n.type = “text/javascript”;

//以上省略部分代碼

//ie支持script的readystatechange屬性(IE support the readystatechange event for script and css nodes)

if(ua.ie){

n.onreadystatechange = function(){

var rs = this.readyState;

if(‘loaded’ === rs || ‘complete’===rs){

n.onreadystatechange = null;

f(id,url); //回調函數

}

};

//省略部分代碼

//safari 3.x supports the load event for script nodes(DOM2)

n.addEventListener(‘load’,function(){

f(id,url);

});

//firefox and opera support onload(but not dom2 in ff) handlers for

//script nodes.opera, but no ff, support the onload event for link

//nodes.

}else{

n.onload = function(){

f(id,url);

};

}

26,js中如何定義class,如何擴展prototype?

Ele.className = “***”; //***在css中定義,形式如下:.*** {…}

A.prototype.B = C;

A是某個構造函數的名字

B是這個構造函數的屬性

C是想要定義的屬性的值

27,如何添加html元素的事件,有幾種方法.

(1)爲HTML元素的事件屬性賦值

(2)在JS中使用ele.on*** = function() {…}

(3)使用DOM2的添加事件的方法 addEventListener或attachEvent

28,documen.write和 innerHTML的區別

document.write只能重繪整個頁面

innerHTML可以重繪頁面的一部分

29,多瀏覽器檢測通過什麼?

(1) navigator.userAgent

(2)不同瀏覽器的特性,如addEventListener

30,js的基礎對象有那些, window和document的常用的方法和屬性列出來

String,Number,Boolean

Window:

方法:setInterval,setTimeout,clearInterval,clearTimeout,alert,confirm,open

屬性:name,parent,screenLeft,screenTop,self,top,status

Document

方法:createElement,execCommand,getElementById,getElementsByName,getElementByTagName,write,writeln

屬性:cookie,doctype,domain,documentElement,readyState,URL,

31,前端開發的優化問題

(1)減少http請求次數:css spirit,data uri

(2) JS,CSS源碼壓縮

(3)前端模板 JS+數據,減少由於HTML標籤導致的帶寬浪費,前端用變量保存AJAX請求結果,每次操作本地變量,不用請求,減少請求次數

(4)用innerHTML代替DOM操作,減少DOM操作次數,優化javascript性能

(5)用setTimeout來避免頁面失去響應

(6)用hash-table來優化查找

(7)當需要設置的樣式很多時設置className而不是直接操作style

(8)少用全局變量

(9)緩存DOM節點查找的結果

(10)避免使用CSS Expression

(11)圖片預載

(12)避免在頁面的主體佈局中使用table,table要等其中的內容完全下載之後纔會顯示出來,顯示比div+css佈局慢

32,如何控制網頁在網絡傳輸過程中的數據量

啓用GZIP壓縮

保持良好的編程習慣,避免重複的CSS,JavaScript代碼,多餘的HTML標籤和屬性

33,Flash、Ajax各自的優缺點,在使用中如何取捨?

Ajax的優勢

(1)可搜索型

(2)開放性

(3)費用

(4)易用性

(5)易於開發

Flash的優勢

(1)多媒體處理

(2)兼容性

(3)矢量圖形比SVG,Canvas優勢大很多

(4)客戶端資源調度,比如麥克風,攝像頭

 

 

4用腳本寫去除字符串的前後空格

 

String.prototype.trim = function(mode)

{//前後去空格

if (mode==’left’) {

return ((this.charAt(0) == ” ” && this.length > 0) ? this.slice(1).trim(‘left’) : this);

} else

if (mode == ‘right’) {

return ((this.charAt(this.length – 1) == ” ” && this.length > 0) ? this.slice(0, this.length – 1).trim(‘right’) : this);

} else {

return this.trim(‘left’).trim(‘right’);

}

};

5算出字符串中出現次數最多的字符是什麼,出現了多少次

 

<script type=”text/javascript”>

//<![CDATA[var str ="adadfdfseffserfefsefseeffffftsdg"; //命名一個變量放置給出的字符串

var maxLength = 0; //命名一個變量放置字母出現的最高次數並初始化爲0

var result = ''; //命名一個變量放置結果輸入

while( str != '' ){ //循環迭代開始,並判斷字符串是否爲空

oldStr = str; //將原始的字符串變量賦值給新變量

getStr = str.substr(0,1); //用字符串的substr的方法得到第一個字符(首字母)

eval("str = str.replace(/"+getStr+"/g,'')"); //詳細如補充

if( oldStr.length-str.length > maxLength )

{ //判斷原始的字符串的長度減去替代後字符串長度是否大於之前出現的最大的字符串長度

maxLength = oldStr.length-str.length; //兩字符串長度相減得到最大的字符串長度

result = getStr + "=" + maxLength //返回最大的字符串結果(字母、出現次數)

}

}

alert(result) //彈出結果

//]]>

</script>

6寫出3中使用this的典型應用

在HTML元素事件屬性中inline方式使用this關鍵字:

7.最後一個問題是,如何製作一個combo選項,就是可以輸入可以下拉菜單選擇。

這個網上有很多成品,主要是通過絕對定位和相對定位結合的方式,改造原有的select 標籤和input標籤的方法。

 

附上javascript正則表達式的基本知識:

g: 全局匹配

i: 忽略大小寫

^ 匹配一個輸入或一行的開頭,/^a/匹配”an A”,而不匹配”An a”

$ 匹配一個輸入或一行的結尾,/a$/匹配”An a”,而不匹配”an A”

* 匹配前面元字符0次或多次,/ba*/將匹配b,ba,baa,baaa

+ 匹配前面元字符1次或多次,/ba*/將匹配ba,baa,baaa

? 匹配前面元字符0次或1次,/ba*/將匹配b,ba

(x) 匹配x保存x在名爲$1…$9的變量中

x|y 匹配x或y

{n} 精確匹配n次

{n,} 匹配n次以上

{n,m} 匹配n-m次

[xyz] 字符集(character set),匹配這個集合中的任一一個字符(或元字符)

[^xyz] 不匹配這個集合中的任何一個字符

[b] 匹配一個退格符

b 匹配一個單詞的邊界

B 匹配一個單詞的非邊界

cX 這兒,X是一個控制符,/cM/匹配Ctrl-M

d 匹配一個字數字符,/d/ = /[0-9]/

D 匹配一個非字數字符,/D/ = /[^0-9]/

n 匹配一個換行符

r 匹配一個回車符

s 匹配一個空白字符,包括n,r,f,t,v等

S 匹配一個非空白字符,等於/[^nfrtv]/

t 匹配一個製表符

v 匹配一個重直製表符

w 匹配一個可以組成單詞的字符(alphanumeric,這是我的意譯,含數字),包括下劃線,如[w]匹配”$5.98″中的5,等於[a-zA-Z0-9]

W 匹配一個不可以組成單詞的字符,如[W]匹配”$5.98″中的$,等於[^a-zA-Z0-9

舉例:驗證email

var myReg = /^[_a-z0-9]+@([_a-z0-9]+.)+[a-z0-9]{2,3}$/;

if(myReg.test(strEmail)) return true;

Date 對象屬性

FF: Firefox, IE: Internet Explorer

 

屬性描述 FF IE

constructor 返回對創建此對象的 Date 函數的引用。 1 4

prototype 使您有能力向對象添加屬性和方法。 1 4

Date 對象方法

FF: Firefox, IE: Internet Explorer

 

方法描述 FF IE

Date() 返回當日的日期和時間。 1 3

getDate() 從 Date 對象返回一個月中的某一天 (1 ~ 31)。 1 3

getDay() 從 Date 對象返回一週中的某一天 (0 ~ 6)。 1 3

getMonth() 從 Date 對象返回月份 (0 ~ 11)。 1 3

getFullYear() 從 Date 對象以四位數字返回年份。 1 4

getYear() 請使用 getFullYear() 方法代替。 1 3

getHours() 返回 Date 對象的小時 (0 ~ 23)。 1 3

getMinutes() 返回 Date 對象的分鐘 (0 ~ 59)。 1 3

getSeconds() 返回 Date 對象的秒數 (0 ~ 59)。 1 3

getMilliseconds() 返回 Date 對象的毫秒(0 ~ 999)。 1 4

getTime() 返回 1970 年 1 月 1 日至今的毫秒數。 1 3

getTimezoneOffset() 返回本地時間與格林威治標準時間 (GMT) 的分鐘差。 1 3

getUTCDate() 根據世界時從 Date 對象返回月中的一天 (1 ~ 31)。 1 4

getUTCDay() 根據世界時從 Date 對象返回週中的一天 (0 ~ 6)。 1 4

getUTCMonth() 根據世界時從 Date 對象返回月份 (0 ~ 11)。 1 4

getUTCFullYear() 根據世界時從 Date 對象返回四位數的年份。 1 4

getUTCHours() 根據世界時返回 Date 對象的小時 (0 ~ 23)。 1 4

getUTCMinutes() 根據世界時返回 Date 對象的分鐘 (0 ~ 59)。 1 4

getUTCSeconds() 根據世界時返回 Date 對象的秒鐘 (0 ~ 59)。 1 4

getUTCMilliseconds() 根據世界時返回 Date 對象的毫秒(0 ~ 999)。 1 4

parse() 返回1970年1月1日午夜到指定日期(字符串)的毫秒數。 1 3

setDate() 設置 Date 對象中月的某一天 (1 ~ 31)。 1 3

setMonth() 設置 Date 對象中月份 (0 ~ 11)。 1 3

setFullYear() 設置 Date 對象中的年份(四位數字)。 1 4

setYear() 請使用 setFullYear() 方法代替。 1 3

setHours() 設置 Date 對象中的小時 (0 ~ 23)。 1 3

setMinutes() 設置 Date 對象中的分鐘 (0 ~ 59)。 1 3

setSeconds() 設置 Date 對象中的秒鐘 (0 ~ 59)。 1 3

setMilliseconds() 設置 Date 對象中的毫秒 (0 ~ 999)。 1 4

setTime() 以毫秒設置 Date 對象。 1 3

setUTCDate() 根據世界時設置 Date 對象中月份的一天 (1 ~ 31)。 1 4

setUTCMonth() 根據世界時設置 Date 對象中的月份 (0 ~ 11)。 1 4

setUTCFullYear() 根據世界時設置 Date 對象中的年份(四位數字)。 1 4

setUTCHours() 根據世界時設置 Date 對象中的小時 (0 ~ 23)。 1 4

setUTCMinutes() 根據世界時設置 Date 對象中的分鐘 (0 ~ 59)。 1 4

setUTCSeconds() 根據世界時設置 Date 對象中的秒鐘 (0 ~ 59)。 1 4

setUTCMilliseconds() 根據世界時設置 Date 對象中的毫秒 (0 ~ 999)。 1 4

toSource() 返回該對象的源代碼。 1 –

toString() 把 Date 對象轉換爲字符串。 1 4

toTimeString() 把 Date 對象的時間部分轉換爲字符串。 1 4

toDateString() 把 Date 對象的日期部分轉換爲字符串。 1 4

toGMTString() 請使用 toUTCString() 方法代替。 1 3

toUTCString() 根據世界時,把 Date 對象轉換爲字符串。 1 4

toLocaleString() 根據本地時間格式,把 Date 對象轉換爲字符串。 1 3

toLocaleTimeString() 根據本地時間格式,把 Date 對象的時間部分轉換爲字符串。 1 3

toLocaleDateString() 根據本地時間格式,把 Date 對象的日期部分轉換爲字符串。 1 3

UTC() 根據世界時返回 1997 年 1 月 1 日到指定日期的毫秒數。 1 3

valueOf() 返回 Date 對象的原始值。 1 4

Array 對象屬性

FF: Firefox, IE: Internet Explorer

屬性

描述

FF 

IE 

constructor

返回對創建此對象的數組函數的引用。

index 

  

input 

  

length

設置或返回數組中元素的數目。

prototype

使您有能力向對象添加屬性和方法。

Array 對象方法

FF: Firefox, IE: Internet Explorer

方法

描述

FF 

IE 

concat()

連接兩個或更多的數組,並返回結果。

join()

把數組的所有元素放入一個字符串。元素通過指定的分隔符進行分隔。

pop()

刪除並返回數組的最後一個元素

5.5 

push()

向數組的末尾添加一個或更多元素,並返回新的長度。

5.5 

reverse()

顛倒數組中元素的順序。

1

shift()

刪除並返回數組的第一個元素

5.5 

slice()

從某個已有的數組返回選定的元素

1

sort()

對數組的元素進行排序

splice()

刪除元素,並向數組添加新元素。

5.5 

toSource()

返回該對象的源代碼。

toString()

把數組轉換爲字符串,並返回結果。

toLocaleString()

把數組轉換爲本地數組,並返回結果。

unshift()

向數組的開頭添加一個或更多元素,並返回新的長度。

valueOf()

返回數組對象的原始值

   

jQuery AJAX 請求

請求

描述

$(selector).load(url,data,callback) 

把遠程數據加載到被選的元素中

$.ajax(options)

把遠程數據加載到 XMLHttpRequest 對象中

$.get(url,data,callback,type) 

使用 HTTP GET 來加載遠程數據

$.post(url,data,callback,type) 

使用 HTTP POST 來加載遠程數據

$.getJSON(url,data,callback) 

使用 HTTP GET 來加載遠程 JSON 數據

$.getScript(url,callback) 

加載並執行遠程的 JavaScript 文件

(selector) jQuery 元素選擇器語法

(url) 被加載的數據的 URL(地址)

(data) 發送到服務器的數據的鍵/值對象

(callback) 當數據被加載時,所執行的函數

(type) 被返回的數據的類型 (html,xml,json,jasonp,script,text)

(options) 完整 AJAX 請求的所有鍵/值對選項

 

AJAX – 瀏覽器支持

AJAX 的要點是 XMLHttpRequest 對象。

不同的瀏覽器創建 XMLHttpRequest 對象的方法是有差異的。

IE 瀏覽器使用 ActiveXObject,而其他的瀏覽器使用名爲 XMLHttpRequest 的 JavaScript 內建對象。

如需針對不同的瀏覽器來創建此對象,我們要使用一條 “try and catch” 語句。您可以在我們的 JavaScript 教程中閱讀更多有關try 和 catch 語句的內容。

讓我們用這段創建 XMLHttpRequest 對象的 JavaScript 來更新一下我們的 “testAjax.htm” 文件:

<html>

<body>

 

<script type=”text/javascript”>

 

function ajaxFunction()

{

var xmlHttp;

 

try

{

// Firefox, Opera 8.0+, Safari

xmlHttp=new XMLHttpRequest();

}

catch (e)

{

 

// Internet Explorer

try

{

xmlHttp=new ActiveXObject(“Msxml2.XMLHTTP”);

}

catch (e)

{

 

try

{

xmlHttp=new ActiveXObject(“Microsoft.XMLHTTP”);

}

catch (e)

{

alert(“您的瀏覽器不支持AJAX!”);

return false;

}

}

}

}

</script>

 

<form name=”myForm”>

用戶: <input type=”text” name=”username” />

時間: <input type=”text” name=”time” />

</form></body>

</html>

例子解釋:

首先聲明一個保存 XMLHttpRequest 對象的 xmlHttp 變量。

然後使用 XMLHttp=new XMLHttpRequest() 來創建此對象。這條語句針對 Firefox、Opera 以及 Safari 瀏覽器。假如失敗,則嘗試針對 Internet Explorer 6.0+ 的 xmlHttp=new ActiveXObject(“Msxml2.XMLHTTP”),假如也不成功,則嘗試針對 Internet Explorer 5.5+ 的 xmlHttp=new ActiveXObject(“Microsoft.XMLHTTP”)。

假如這三種方法都不起作用,那麼這個用戶所使用的瀏覽器已經太過時了,他或她會看到一個聲明此瀏覽器不支持 AJAX 的提示。

註釋:上面這些瀏覽器定製的代碼很長,也很複雜。不過,每當您希望創建 XMLHttpRequest 對象時,這些代碼就能派上用場,因此您可以在任何需要使用的時間拷貝粘貼這些代碼。上面這些代碼兼容所有的主流瀏覽器:Internet Explorer、Opera、Firefox 以及 Safari。

下一節爲您展示如何使用 XMLHttpRequest 對象與服務器進行通信。

AJAX – 更多有關 XMLHttpRequest 對象的知識

在向服務器發送數據之前,我們有必要解釋一下 XMLHttpRequest 對象的三個重要的屬性。

onreadystatechange 屬性

onreadystatechange 屬性存有處理服務器響應的函數。下面的代碼定義一個空的函數,可同時對 onreadystatechange 屬性進行設置:

xmlHttp.onreadystatechange=function()

{

// 我們需要在這裏寫一些代碼

}

readyState 屬性

readyState 屬性存有服務器響應的狀態信息。每當 readyState 改變時,onreadystatechange 函數就會被執行。

這是 readyState 屬性可能的值:

狀態

描述

請求未初始化(在調用 open() 之前)

請求已提出(調用 send() 之前)

請求已發送(這裏通常可以從響應得到內容頭部)

請求處理中(響應中通常有部分數據可用,但是服務器還沒有完成響應)

請求已完成(可以訪問服務器響應並使用它)

我們要向這個 onreadystatechange 函數添加一條 If 語句,來測試我們的響應是否已完成(意味着可獲得數據):

xmlHttp.onreadystatechange=function()

{

if(xmlHttp.readyState==4)

{

// 從服務器的response獲得數據

}

}

responseText 屬性

可以通過 responseText 屬性來取回由服務器返回的數據。

在我們的代碼中,我們將把時間文本框的值設置爲等於 responseText:

xmlHttp.onreadystatechange=function()

{

if(xmlHttp.readyState==4)

{

document.myForm.time.value=xmlHttp.responseText;

}

}

下一節,我們會介紹如何向服務器請求數據!

AJAX – 向服務器發送一個請求

要想把請求發送到服務器,我們就需要使用 open() 方法和 send() 方法。

open() 方法需要三個參數。第一個參數定義發送請求所使用的方法(GET 還是 POST)。第二個參數規定服務器端腳本的 URL。第三個參數規定應當對請求進行異步地處理。

send() 方法可將請求送往服務器。如果我們假設 HTML 文件和 ASP 文件位於相同的目錄,那麼代碼是這樣的:

xmlHttp.open(“GET”,”time.asp”,true);

xmlHttp.send(null);

現在,我們必須決定何時執行 AJAX 函數。當用戶在用戶名文本框中鍵入某些內容時,我們會令函數”在幕後”執行。

<html>

<body>

 

<script type=”text/javascript”>

 

function ajaxFunction()

{

var xmlHttp;

 

try

{

// Firefox, Opera 8.0+, Safari

xmlHttp=new XMLHttpRequest();

}

catch (e)

{

 

// Internet Explorer

try

{

xmlHttp=new ActiveXObject(“Msxml2.XMLHTTP”);

}

catch (e)

{

 

try

{

xmlHttp=new ActiveXObject(“Microsoft.XMLHTTP”);

}

catch (e)

{

alert(“您的瀏覽器不支持AJAX!”);

return false;

}

}

}

    
 

xmlHttp.onreadystatechange=function()

{

if(xmlHttp.readyState==4)

{

document.myForm.time.value=xmlHttp.responseText;

}

}

xmlHttp.open(“GET”,”time.asp”,true);

xmlHttp.send(null);

    

}

</script>

 

<form name=”myForm”>

用戶: <input type=”text” name=”username” onkeyup=”ajaxFunction();” />

時間: <input type=”text” name=”time” />

</form>

 

</body>

</html>

通過微軟的 XML 解析器來加載 XML

微軟的 XML 解析器內建於 Internet Explorer 5 以及更高的版本中。

下面的 JavaScript 片段把一個 XML 文檔載入解析器中:

var xmlDoc=new ActiveXObject(“Microsoft.XMLDOM”);

xmlDoc.async=”false”;

xmlDoc.load(“note.xml”);

例子解釋:

上面代碼的第一個行創建一個空的微軟 XML 文檔對象。

第二行關閉異步加載,這樣確保在文檔完全加載之前解析器不會繼續腳本的執行。

第三行告知解析器加載名爲 “note.xml” 的 XML 文檔。

下面的 JavaScript 片段把字符串 txt 載入解析器:

var xmlDoc=new ActiveXObject(“Microsoft.XMLDOM”);

xmlDoc.async=”false”;

xmlDoc.loadXML(txt);

註釋:loadXML()方法用於加載字符串(文本),load() 用於加載文件。

在 Firefox 及其他瀏覽器中的 XML 解析器

下面的 JavaScript 片段把 XML 文檔 (“note.xml”) 載入解析器:

var xmlDoc=document.implementation.createDocument(“”,””,null);

xmlDoc.async=”false”;

xmlDoc.load(“note.xml”);

例子解釋:

上面代碼的第一個行創建一個空的 XML 文檔對象。

第二行關閉異步加載,這樣確保在文檔完全加載之前解析器不會繼續腳本的執行。

第三行告知解析器加載名爲 “note.xml” 的 XML 文檔。

下面的 JavaScript 片段把字符串 txt 載入解析器:

var parser=new DOMParser();

var doc=parser.parseFromString(txt,”text/xml”);

例子解釋:

上面代碼的第一個行創建一個空的微軟 XML 文檔對象。

第二行告知解析器載入名爲 txt 的字符串。

註釋:Internet

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章