(1)、if 判斷html
if 語句是基於條件成立時才執行相應的代碼。json
if...else 語句是在指定的條件成立時執行if後的代碼,在條件不成立時執行else後的代碼。跨域
if...else 嵌套語句是在多種條件下選擇相應的代碼快之一來執行。數組
if 語句適用於任意類型的數據,可處理複雜的邏輯關係。瀏覽器
(2)、switch語句安全
當有不少種選擇的時候,switch 比 if...else 使用更方便,結構簡潔,專爲多重選擇設計,可是僅能處理多個枚舉型邏輯關係。該語句使用 if 也能夠完成,這個看我的喜愛。服務器
switch 語句的工做原理:首先建立一個表達式,一般爲變量,以後表達式的值與 switch 語句中每一個 case 的值作比較,若是匹配,則執行該 case 後的語句,若與全部 case 值都不匹配,則執行 default 後的語句。在使用 switch 語句時,每一個 case 語句後必須使用 break 跳出循環,阻止運行下一個 case。閉包
1 var d = new Date().getDay(); 2 //若是今天不是週末,則提示默認消息 3 switch (d){ 4 case 6: 5 alert("今天是星期六"); 6 break; 7 case 0: 8 alert("今天是星期天"); 9 break; 10 default: 11 alert("同志還沒有努力,革命仍需成功。"); 12 }
switch 語句在作比較時,使用的是全等,而不是相等,因此在字符串與數字匹配時,須要特別注意。dom
1 //使用switch語句將字符串與數字作比較 2 //返回:不等於,執行default語句 3 var n = '5'; 4 switch(n){ 5 case 5: 6 alert('等於,執行case語句'); 7 break; 8 default: 9 alert('不等於,執行default語句'); 10 } 11 12 //使用if語句將字符串與數字作比較 13 //返回:等於 14 var n = '2'; 15 if(n == 2){ 16 alert('等於'); 17 }else{ 18 alert('不等於'); 19 } 20 21 //將case的值改成字符串再作比較 22 //返回:等於,執行case語句 23 var n = '2'; 24 switch(n){ 25 case '2': 26 alert('等於,執行case語句'); 27 break; 28 default: 29 alert('不等於,執行default語句'); 30 } 31 32 33 //使用全等再作比較 34 //返回:不等於 35 var n = '2'; 36 if(n===2){ 37 alert('等於'); 38 }else{ 39 alert('不等於'); 40 }
(3)、for 循環異步
不少事情不僅是作一次,須要重複作。好比打印 10 份文件,每次打印 1 份,重複這個動做,直到打印完成。這樣的事情就用 for 循環來完成,循環就是重複執行一段代碼,每次的值不一樣。
下面是一個 for 循環的小應用,假設有 1.2.3. ... 10 不一樣面值的 RMB,計算一共有多少 RMB。
1 var sum = 0; 2 for(var rmb=1; rmb<=10; rmb++){ 3 sum += rmb; 4 } 5 alert('一共有: ' + sum + '元'); //返回:一共有:55元
(4)、while 循環
while 循環和 for 循環具備相同的功能,只要指定條件爲 ture,循環就能夠一直執行,直到條件再也不知足。
1 //使用while循環輸出5個數字 2 var i = 0; //第一部分:初始化,給一個初始的值,讓i從0循環 3 while(i < 5){ //第二部分:條件。成立繼續循環,不成立退出 4 alert(i); //第三部分:語句 5 i++; //第四部分:自增 6 } 7 //while循環使用比較複雜,使用for循環更簡潔。 8 //for(初始化;條件;自增){語句}
(5)、do...while 循環
do...while 循環與 while 循環的原理結構是基本相同的,可是該循環會在檢查條件是否爲 ture 以前執行一次代碼塊,若是條件爲 ture,則重複循環。該循環有一點小問題,由於他是先執行代碼,後判斷條件,若是條件不當,則進入死循環,致使瀏覽器崩潰。
1 /* 2 語法: 3 do{ 4 執行語句 5 } 6 while(條件); 7 */ 8 9 //操做有風險,嘗試需謹慎 10 //若將循環條件改成:num <= 6 會致使瀏覽器崩潰 11 var num = 6; 12 do{ 13 document.write("數字:" + num + "<br>"); 14 num -= 1; 15 } 16 while(num > 0);
(6)、JS 錯誤處理語句
try...catch 語句用於進行異常處理。try 語句用於檢測代碼塊的錯誤,指明須要處理的代碼段,catch 語句用於處理 try 語句中拋出的錯誤。try 語句首先被執行,若是運行中發生了錯誤,try 語句中的代碼將被跳過執行 catch 中的語句。若是沒有發生錯誤,則不執行 catch 中的語句。通常針對可預見性的錯誤,可以使用 try...catch 語句進行處理。
1 try{ 2 document.write("開始執行try語句" + '<br>'); 3 document.write("還沒拋出錯誤" + '<br>'); 4 alert(x); //拋出錯誤 5 alert('123'); //沒被執行 6 } 7 catch(e){ 8 document.write("捕捉到錯誤,開始執行catch語句" + '<br>'); 9 document.write("錯誤類型: " + e.name + '<br>'); 10 document.write("錯誤信息: " + e.message); 11 alert('x'); 12 }
throw 語句可用於建立自定義錯誤。官方術語爲:建立或拋出異常(exception)。語法:throw '異常對象'。
throw 語句能夠配合 try...catch 語句一塊兒使用,以達到控制程序流,生成精確的錯誤消息。
1 //輸入0到10之間的數字,若是輸入錯誤,會拋出一個錯誤,catch會捕捉到錯誤,並顯示自定義的錯誤消息。 2 <body> 3 <input id="txt" type="text"/> 4 <span id="demo" style="font-weight:bold;"></span><br> 5 <input type="button" value="檢測輸入" onclick="error()"> 6 <script> 7 function error(){ 8 try{ 9 var x = document.getElementById("txt").value; 10 var y = document.getElementById("demo"); 11 y.style.color = 'red'; 12 if(x == '') throw '輸入不能爲空'; 13 if(isNaN(x)) throw '請輸入數字'; 14 var num = [7,8,9]; 15 for(var i=0; i<num.length; i++){ 16 if(x == num[i]){ 17 throw '該數字已經存在'; 18 } 19 } 20 if(x == 0){ 21 throw '輸入不能爲0'; 22 } 23 else if(x > 10){ 24 throw '數字太大了'; 25 } 26 else if(x <= 3){ 27 throw '數字過小了'; 28 } 29 else{ 30 y.style.color = 'green'; 31 y.innerHTML = 'OK'; 32 } 33 } 34 catch(e){ 35 y.innerHTML = '錯誤提示:' + e + '!'; 36 } 37 } 38 </script> 39 </body>
(7)、跳出循環
break 語句用於跳出當前循環,直接退出循環執行後面的代碼,即終止整個循環,再也不進行判斷。continue 語句僅僅是跳出本次循環,繼續執行後面的循環,即結束本次循環,接着去判斷是否執行下次循環。return 能夠終止函數體的運行,並返回一個值。
1 for(var i=0; i<6; i++){ 2 if(i == 3) break; //當i=3時跳出整個循環,再也不執行循環 3 alert(i); //返回:0,1,2 4 } 5 6 for(var i=0; i<6; i++){ 7 if(i == 3) continue; //當i=3時跳出本次循環,繼續執行後面循環 8 alert(i); 返回:0,1,2,4,5 9 }
JSON(JavaScript Object Notation):JS 對象表示法。JSON 主要用於存儲和交換數據信息,相似於 XML,可是相比 XML,JSON 易於閱讀和編寫,也易於解析。
JSON 語法是 JS 對象表示語法的子集:數據在鍵值對中,並由逗號分隔,花括號保存對象,方括號保存數組。
JSON 語法的書寫格式:"名稱" : "值", "名稱" : "值"
名稱和值包含在雙引號中,並用冒號分隔,每條數據用逗號分隔。這很容易理解,相對於 JS 中 名稱 = "值"。
JSON 的值能夠是:數字(包括整數和小數),字符串(包含在雙引號中),布爾值(true 或 false),對象(包含在花括號中),數組(包含在方括號中),或者爲 null。
JSON 是純文本,一般用於服務端向網頁傳遞數據,從服務器上獲取 JSON 數據,而後在網頁中使用該數據。
(1)、JSON對象
1 var json = {"a": 12, "b": "abc", "c":[1,2,3]}; 2 //返回第一項的值: 3 alert(json.a); 4 5 //修改第二項的值 6 alert(json.b = "xyz"); 7 8 //返回第三項數組中第一項的值 9 alert(json.c[0]);
(2)、JSON 和數組
相同點:
均可以經過下標返回某項的值。均可以使用循環。雖然 JSON 沒有 length 屬性,不能使用 for 循環,可是可使用 for...in 循環,完成與 for 循環相同的動做。
數組也可使用 for...in 循環,但最好仍是使用 for 循環。for...in 循環遍歷的是對象的屬性,而不是數組元素。
不一樣點:
JSON 的下標是字符串,數組的下標爲數字。JSON 沒有 length 屬性,數組有該屬性。
1 var arr = [12,5,7]; 2 var json = {"a":12,"b":5,"c":7}; 3 4 alert(arr[0]); //返回:12 5 alert(json["a"]); //返回:12 6 7 alert(arr.length); //返回:3 8 alert(json.length); //返回:undefined 9 10 //數組for循環 11 for(var i=0; i<arr.length; i++){ 12 alert('第' + (i+1) + '個數據是:' + arr[i]); 13 } 14 alert(typeof i); //返回:number 15 16 //數組使用for...in循環 17 for(var i in arr){ 18 alert('第' + (i+1) + '個數據是:' + arr[i]); 19 } 20 alert(typeof i); //返回:string 21 22 //JSON使用for...in循環 23 for(var i in json){ 24 alert('第' + i + '個數據是:' + json[i]); 25 }
(3)、JSON 數組對象
1 <body> 2 <p> 3 姓 名: <span id="fname"></span><br> 4 性 別: <span id="gender"></span><br> 5 員工號: <span id="num"></span><br> 6 修改姓名: <span id="lname"></span><br> 7 </p> 8 <script> 9 var staff = [ 10 {"name" : "小明", "sex" : "男", "id" : 1}, 11 {"name" : "小白", "sex" : "男", "id" : 2}, 12 {"name" : "小紅", "sex" : "女", "id" : 3} 13 ]; 14 var x = document.getElementById("fname"); 15 var y = document.getElementById("gender"); 16 var z = document.getElementById("num"); 17 var n = document.getElementById("lname"); 18 //訪問對象數組中第一項的值: 19 x.innerHTML = staff[0].name; 20 y.innerHTML = staff[0].sex; 21 z.innerHTML = staff[0].id; 22 23 //修改數據: 24 n.innerHTML = staff[1].name = '大白'; 25 </script> 26 </body>
(4)、JSON 字符串對象
var str = '{"name":"小明", "sex":"男", "age":21}'; var toObj = JSON.parse(str); //JSON字符串轉換爲JSON對象 alert(toObj.name); alert(typeof toObj); //返回:object var json = {"name":"小紅", "sex":"女", "age":18}; var toStr = JSON.stringify(json); //JSON對象轉換爲JSON字符串 alert(toStr); //返回字符串 alert(json.age); alert(typeof toStr); //返回:string
(5)、JSON 應用
當須要表示一組數據時,JSON 不但可以提升可讀性,並且還能夠減小複雜性。JSON 可以表示多個值,每一個值又可包含多個值,例如要表示一個用戶列表信息,就能夠將全部信息存儲在一個變量中,分紅多項,每項中又可分紅多個條目,每一個條目中記錄一個用戶的信息。
1 var userName = { 2 "first": [{ 3 "name": "路飛", 4 "sex": "男", 5 "tel": "aaa" 6 }, { 7 "name": "索羅", 8 "sex": "男", 9 "tel": "bbb" 10 }, { 11 "name": "娜美", 12 "sex": "女", 13 "tel": "ccc" 14 }], 15 16 "second": [{ 17 "name": "卡卡西", 18 "sex": "男", 19 "tel": "ddd" 20 }, { 21 "name": "鳴人", 22 "sex": "男", 23 "tel": "fff" 24 }, { 25 "name": "佐助", 26 "sex": "男", 27 "tel": "eee" 28 }, { 29 "name": "皺田", 30 "sex": "女", 31 "tel": "sss" 32 }], 33 34 "third": [{ 35 "name": "小明", 36 "sex": "男", 37 "tel": "xxx" 38 },{ 39 "name": "小紅", 40 "sex": "女", 41 "tel": "zzz" 42 }] 43 }; 44 45 //獲取用戶的信息: 46 alert(userName.first[1].name + ' \n ' + userName.first[1].sex + '\n '+ userName.first[1].tel); 47 alert(userName.second[3].name + ' \n ' + userName.second[3].sex +' \n '+ userName.second[3].tel); 48 alert(userName.third[0].name + ' \n ' + userName.third[0].sex + ' \n '+ userName.third[0].tel);
說到 JSON,就不得不提一下 JSONP。JSONP (JSON with Padding) 是 JSON 的一種 "使用模式",可讓網頁從別的域名(網站)那獲取資料,即跨域讀取數據。可用於解決主流瀏覽器的跨域數據訪問的問題。爲何從不一樣的域(網站)訪問數據須要一個特殊的技術 (JSONP) 呢?這是由於同源策略。同源策略,它是由 Netscape 提出的一個著名的安全策略,如今全部支持 JavaScript 的瀏覽器都會使用這個策略。因爲該策略,通常來講位於 server1 的 demo.com 的網頁沒法與不是 server1 的 demo.com 的網頁的服務器溝通,而 HTML 的 <script> 元素是一個例外。利用 <script> 元素的這個開放策略,網頁能夠獲得從其餘來源動態產生的 JSON 資料,而這種使用模式就是所謂的 JSONP。用 JSONP 抓到的資料並非 JSON,而是任意的 JavaScript,用 JavaScript 直譯器執行而不是用 JSON 解析器解析。
定時器能夠在指定的時間間隔以後再執行代碼,而不是在函數被調用後當即執行。定時器在網頁中應用很是普遍,最多見的就是動態時鐘,還有好比購物網站的倒計時搶購。定時器的類型可分爲兩類:一類是間隔型,即 setInterval,在執行時,從頁面加載後每隔一段時間執行一次,可無限執行。另外一類是延遲型,即 setTimeout,在頁面加載後延遲指定的時間,去執行一次,並且僅僅只執行一次。該方法屬於 window 對象的兩個方法。
(1)、setInterval
setInterval(function, time) 方法可間隔指定的毫秒數,不停的執行指定的代碼。該方法有兩個參數,第一個參數是函數,指定定時器要調用的函數或要執行的代碼串,第二個參數是時間,用毫秒計,1000 毫秒是 1 秒,指定執行的間隔時間。
(2)、setTimeout
setTimeout(function, time) 方法可延遲指定的毫秒數後,再執行一次指定的代碼。該方法也有兩個參數,第一個參數爲函數,指定要調用的函數或代碼串,第二個參數指定在執行代碼前須要等待多少毫秒。
1 function show(){ 2 alert(1); 3 } 4 //當頁面加載後,每隔1秒彈出一個1,無限次執行 5 setInterval(show,1000); 6 7 //當頁面加載後,在1秒後彈出一個1,只執行一次 8 setTimeout(show,1000);
setInterval 動態時鐘效果:
1 //動態顯示時鐘 2 <p id="demo"></p> 3 <script> 4 function clock(){ 5 var d = new Date(); 6 var time = d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds() ; 7 var oP = document.getElementById("demo").innerHTML = time; 8 } 9 setInterval(clock,1000); 10 </script>
setTimeout 統計效果:
1 //setTimeout可實現統計: 2 <input type="text" id="demo" > 3 <script> 4 var num = 0; 5 function start() { 6 document.getElementById('demo').value = num; 7 num += 1; 8 setTimeout(start,1000); 9 } 10 setTimeout(start,1000); 11 </script>
能夠開啓定時器,也就能夠關閉定時器。兩種類型對應着兩種方法。
(1)、clearInterval
clearInterval() 方法可關閉由 setInterval() 方法執行的函數代碼。使用該方法關閉定時器時,在建立間隔定時器時必須使用全局變量。
開始、中止動態時鐘效果:
1 //開始、中止動態時鐘 2 <input type="text" id="txt1" > 3 <input type="button" value="中止" onclick="stop()" > 4 <input type="button" value="開始" onclick="start()" > 5 <script> 6 var time = null; 7 function start(){ 8 time = setInterval(function (){ 9 var d = new Date(); 10 var t = d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds(); 11 var oTxT = document.getElementById("txt1").value = t; 12 },1000); 13 }; 14 start(); 15 function stop(){ 16 clearInterval(time); 17 } 18 </script>
(2)、clearTimeout
clearTimeout() 方法用於中止執行由 setTimeout() 方法執行的函數代碼。使用該方法時關閉定時器時,在建立延遲定時器時必須使用全局變量。
開始、中止統計效果:
1 //開始、中止統計: 2 <input type="text" id="txt1" > 3 <input type="button" value="中止" onclick="stop()" > 4 <input type="button" value="開始" onclick="start()" > 5 <script> 6 var num = 0; 7 var time = null; 8 function start(){ 9 var oTxt = document.getElementById('txt1').value = num; 10 num += 1; 11 time = setTimeout('start()',1000); 12 } 13 start(); 14 function stop(){ 15 clearTimeout(time); 16 } 17 </script>
event 對象表明事件的狀態,用於獲取事件的詳細信息,如鼠標按鈕、鼠標位置、鍵盤按鍵。事件一般與函數一塊兒使用,函數不會在事件發生前被執行。
(1)、獲取鼠標座標
screenX 和 screenY 返回鼠標相對於屏幕的水平座標和垂直座標。參照點爲屏幕的左上角。
clientX 和 clientY 返回鼠標相對於當前窗口可視區的水平座標和垂直座標。參照點爲瀏覽器頁面的左上角。
1 document.onclick = function (){ 2 //可視區座標 3 alert(event.clientX + ',' + event.clientY); 4 //屏幕座標 5 alert(event.screenX + ',' + event.screenY); 6 }
(2)、獲取鼠標鈕按
button 事件屬性用於獲取鼠標哪一個按鈕被點擊了。返回一個整數,0 表明左鍵,1 表明中鍵,2 表明右鍵。
1 //鼠標左右按鍵 2 document.onmousedown = function (){ 3 alert(event.button); 4 }
(3)、獲取鍵盤按鍵
keyCode 事件屬性用於獲取按下了鍵盤的哪一個鍵,返回鍵碼,表示鍵盤上真實鍵的數字。
1 //鍵盤按鍵 2 document.onkeydown=function (){ 3 alert(event.keyCode); 4 };
鍵盤按鍵的 ctrlKey、shiftKey 和 altKey 快捷屬性,可判斷是否按下了該鍵,返回一個布爾值,指示在事件發生時,改鍵是否被按下。1 表示被按下,0 表示沒有按下。
1 document.onkeydown = function (){ 2 if(event.ctrlKey == 1){ 3 alert('Ctrl鍵被按了'); 4 } 5 else if(event.shiftKey == 1){ 6 alert('Shift鍵被按了'); 7 } 8 else if(event.altKey == true){ 9 alert('Alt鍵被按了'); 10 } 11 else{ 12 alert('都沒被按下'); 13 } 14 };
實例:按鍵提交消息
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8" /> 5 <title>JavaScript示例</title> 6 <script> 7 window.onload=function (){ 8 var oTxt1 = document.getElementById('txt1'); 9 var oTxt2 = document.getElementById('txt2'); 10 var oBtn = document.getElementById('btn1'); 11 12 //點擊按鈕提交 13 oBtn.onclick = function (){ 14 //輸入框的值等於文本框的值。 15 oTxt2.value += oTxt1.value + '\n'; 16 //清空輸入框的值,以便再次輸入 17 oTxt1.value = ''; 18 }; 19 20 21 //按Enter或Ctrl+Enter提交 22 oTxt1.onkeydown = function (){ 23 //回車鍵的鍵碼爲13 24 if(event.keyCode == 13 || event.keyCode == 13 && event.ctrlKey){ 25 oTxt2.value += oTxt1.value + '\n'; 26 oTxt1.value = ''; 27 } 28 }; 29 } 30 </script> 31 </head> 32 <body> 33 <input id="txt1" type="text" > 34 <input id="btn1" type="button" value="提交"><br> 35 <textarea id="txt2" rows="10" cols="50" ></textarea> 36 </body> 37 </html>
(4)、事件流
事件的傳遞有兩種方式:冒泡與捕獲。事件傳遞定義了元素觸發事件的順序。
事件冒泡:當一個元素髮生事件後,事件會順着層級(父級 - 父級的父級 --)關係依次向上傳遞直到 document。
事件捕獲:事件捕獲與事件冒泡正好相反,外部元素的事件會先被觸發,而後纔會觸發內部元素的事件,即從祖先到後代。
事件流同時支持兩種事件方式,冒泡型事件和捕獲型事件,可是捕獲型事件先發生。
兩種事件流會觸發 DOM 中的全部對象,從 document 對象開始,也在 document 對象結束。
語法:addEventListener('事件名稱',函數,冒泡/捕獲)
addEventListener() 方法用於向指定元素添加事件,該方法不會覆蓋已存在的事件,可同時向一個元素添加多個事件。該方法有三個參數,第一個參數定義事件的類型,
第二個參數規定事件觸發後調用的函數,第三個參數是布爾值,用於定義該事件是冒泡仍是捕獲,若爲 false,則表示冒泡事件,如果 ture,則表示捕獲事件。
這裏須要注意是的該方法的事件類型,不須要加」on「,好比平時寫點擊事件:「onclick」,該方法中則使用「click」便可。
1 <!DOCTYPE html> 2 <html id="htm"> 3 <head> 4 <meta charset="utf-8" /> 5 <title>JavaScript示例</title> 6 <style> 7 div{padding:50px;} 8 </style> 9 <script> 10 window.onload = function (){ 11 var x = document.getElementById("div1"); 12 var y = document.getElementById("div2"); 13 var z = document.getElementById("div3"); 14 15 var o = document.getElementById("bod"); 16 var n = document.getElementById("htm"); 17 18 x.addEventListener("click", function() { 19 alert("1冒泡"); 20 }, false); 21 22 y.addEventListener("click", function() { 23 alert("2冒泡"); 24 }, false); 25 26 z.addEventListener("click", function() { 27 alert("3冒泡"); 28 }, false); 29 30 o.addEventListener("click", function() { 31 alert("body捕獲"); 32 }, true); 33 34 n.addEventListener("click", function() { 35 alert("html冒泡"); 36 }, false); 37 }; 38 </script> 39 </head> 40 <body id="bod"> 41 <div style="background:lightgreen;margin-bottom:10px;">我是body元素,我捕獲。祖先html也會冒泡。</div> 42 <div id="div3" style="background:#ccc;">我是div3,我冒泡 43 <div id="div2" style="background:green;">我是div2,我冒泡 44 <div id="div1" style="background:red;">我是div1,我冒泡</div> 45 </div> 46 </div> 47 </body> 48 </html>
removeEventListener() 方法用於移除由 addEventListener() 方法添加的事件監聽。這裏須要注意在綁定函數時不能使用匿名函數,不然沒法刪除。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>JavaScript示例</title> 6 <style> 7 #div1{ 8 background:green; 9 padding:50px; 10 color:white; 11 } 12 </style> 13 </head> 14 <body> 15 <div id="div1"> 16 div元素添加了onmousemove事件監聽,鼠標在綠色區域內移動時會顯示隨機數。 17 <p>點擊按鈕可移除div的事件監聽。</p> 18 <button id="btn1">點擊移除</button> 19 </div> 20 <p id="p1"></p> 21 22 <script> 23 var oDiv = document.getElementById("div1"); 24 var oP = document.getElementById("p1"); 25 var oBtn = document.getElementById("btn1"); 26 27 oDiv.addEventListener("mousemove", block, false); 28 function block(){ 29 oP.innerHTML = Math.random()*10; 30 } 31 oBtn.onclick = function (){ 32 oDiv.removeEventListener("mousemove", block, false); 33 }; 34 </script> 35 </body> 36 </html>
cancelBubble 方法可取消事件冒泡,不會往父級傳遞。實例:仿百度翻譯效果,點擊顯示按鈕顯示 div,隨便點擊頁面其餘位置隱藏 div。
若是不取消事件冒泡,則在點擊按鈕的同時 div 先是顯示了,而後又立馬被隱藏了,能夠註釋掉取消事件冒泡代碼,用彈窗查看效果。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>JavaScript示例</title> 6 <style> 7 #div1{ 8 width:500px; 9 height:300px; 10 background:lightgreen; 11 display:none; 12 } 13 </style> 14 <script> 15 window.onload = function (){ 16 var oBtn = document.getElementById("btn1"); 17 var oDiv = document.getElementById("div1"); 18 19 //點擊按鈕顯示div 20 oBtn.onclick = function (){ 21 oDiv.style.display = 'block'; 22 //alert('顯示'); 23 24 //取消事件冒泡,不會往父級傳遞。 25 event.cancelBubble = true; 26 }; 27 28 //點擊document隱藏div 29 document.onclick = function (){ 30 oDiv.style.display = 'none'; 31 }; 32 }; 33 </script> 34 </head> 35 <body> 36 <input id="btn1" type="button" value="顯示"> 37 <div id="div1"></div> 38 </body> 39 </html>
(5)、默認事件
所謂的默認事件,就是瀏覽器自帶的事件。好比按下鍵盤按鍵,瀏覽器會自動將按鍵值寫入輸入框。再好比新建一個空白頁面在瀏覽器打開,點擊右鍵出現菜單項。咱們並無用 JS 寫相關判斷,若是點擊右鍵觸發什麼事件。這就是瀏覽器的默認事件,也叫默認行爲。若是咱們想彈出自定義的右鍵菜單項,這時候就須要阻止掉瀏覽器的默認行爲,阻止默認事件最簡單的寫法就是 return false; 。
實例:只能輸入數字鍵的輸入框,不考慮小鍵盤區。
實現思路:鍵盤區數字鍵 0 的鍵碼是 48,1 是 49,9 是 57,那麼就能夠作出判斷,若是按鍵小於 48 或大於 57,則阻止掉,這說明按下的不是數字鍵,考慮到寫錯了須要刪除,或者少寫了,須要光標移動到少寫的位置補上,再移回繼續輸入,那麼就再加上判斷條件,若是按鍵不是退格鍵或者不是左右方向鍵,則阻止掉。刪除鍵(退格鍵)的鍵碼是 8,左方向鍵是 37,右方向鍵爲 39。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>JavaScript示例</title> 6 <script> 7 window.onload = function (){ 8 var oTxt = document.getElementById('txt1'); 9 oTxt.onkeydown = function (){ 10 11 //若是按下的不是刪除鍵8,而且不是左方向鍵37,而且不是右方向鍵39,而且按鍵鍵碼小於48或大於57,則阻止掉 12 if(event.keyCode !=8 && event.keyCode != 37 && event.keyCode != 39 && event.keyCode < 48 || event.keyCode > 57){ 13 return false; 14 } 15 }; 16 }; 17 </script> 18 </head> 19 <body> 20 <input id="txt1" type="text" placeholder="請輸入數字"> 21 </body> 22 </html>
(1)、JS 引擎的預解析機制
JS 引擎的解析過程可分爲兩個階段:預解析階段和執行階段。
JS 預解析是在程序進入一個新環境時,把該環境中的變量和函數預解析到他們能調用的環境中,即每一次的預解析單位是一個執行環境。當文檔流中有多個 JS 代碼段,每一個代碼段用 script 標籤分隔,包括外部引入的 JS 文件,JS 引擎並不是是逐行的解析程序,而是分段進行的,即一個執行環境。預解析不能跨代碼段執行,簡單說就是不能在一個代碼段聲明,在另外一個代碼段調用。
變量和函數的預解析就是提高,所謂提高(hoisting),就是 JS 引擎在執行時,默認將全部的變量聲明和函數聲明都提高到當前做用域的最前邊去的行爲。因此函數能夠在聲明以前調用。須要注意的是在使用表達式定義函數時沒法提高。
1 <script> 2 alert(a(2)); //返回:4 3 function a(x){ 4 return x * x; 5 } 6 7 alert(b); //返回:undefined 8 var b = 'hello'; 9 10 alert(c(2)); //報錯 11 //其實是以變量聲明提高 12 //至關於:c(); var c = undefined; c = function (){} 13 var c = function (y){ 14 return y * y; 15 } 16 17 function d(){ 18 var n = 'hello'; 19 } 20 alert(n); //報錯 21 </script>
經過上面的代碼能夠看出,function 定義的函數聲明 (a) 在代碼開始執行以前(預解析階段)對其實現了函數聲明提高,先將其放入內存中,因此在函數聲明以前能夠調用該函數。和函數聲明同樣,變量聲明 (b) 也會在一開始被放入內存中,可是並無賦值,因此在他賦值以前,他的值就是 undefined。可是函數表達式 (c) 不一樣,函數表達式用 var 聲明,也就是說解析器會對其變量提高,並對其賦值爲 undefined,而後在執行期間,等到執行到該 var 變量的時候再將其變量指向一個 function 函數,因此在函數表達式以前執行該函數就會報錯。函數 (d) 是在函數內聲明的變量,那麼這個變量是屬於該函數的私有變量,因此在外部調用時會報錯。
下面實例實例說明了每一次 JS 預解析的單位是一個執行環境,不會跨一個代碼段去執行,直接會報錯。
1 <script> 2 alert(a);//報錯:a is not defined 3 </script> 4 5 <script> 6 var a = 'hello'; 7 </script>
若定義了兩個同名的函數 (b),則在預解析時後面的一個會覆蓋掉前邊的一個。若變量 (a) 和函數重名 (a),則函數的優先級高於變量的優先級。
1 <script> 2 alert(a); //返回:function a(){alert('hi');} 3 var a = 'hello'; 4 5 function a(){ 6 alert('hi'); 7 } 8 alert(a); //返回:hello 9 10 b(); //返回:2 11 function b(){ 12 alert(1); 13 } 14 b(); //返回:2 15 function b(){ 16 alert(2); 17 } 18 </script>
(2)、回調函數
簡單理解,所謂回調,就是回頭調用,那麼回調函數就是一個函數調用的過程。好比函數 a 有一個參數,這個參數是一個函數 b,當函數 a 執行完之後再執行函數 b,那麼這就是一個回調的過程。用官方術語解釋就是:回調是一個函數做爲參數傳遞給另外一個函數,其母函數完成後執行。那麼函數 a 就是母函數。這裏須要注意:函數 b 是以參數的形式傳遞給函數 a 的,那麼這個函數 b 就被稱爲回調函數。回調函數不是由母函數直接調用的,而是在特定的事件或者條件發生時由另外的一方調用,用於對該事件進行響應。回調函數必須使用關鍵字 callback,而且回調函數自己必須是全局函數。
JS 回調的原理是一個異步的流程,在異步調用的狀況下使用性能很好,舉個簡單的例子更能具體的說明,好比朋友要來找你,等到門口了給你打電話。"來找你" 就是函數 a 開始執行,而這時候"你"能夠去作任何事情,"到門口"就是函數 a 執行完畢,"給你打電話"這就屬於回調函數 b,而後大家就能夠一塊兒愉快的玩耍了。
下面是一個簡單的回調函數實例,點擊按鈕,當函數 a 執行完成後,分別調用回調函數 b、c、d。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>JavaScript示例</title> 6 <script> 7 function a(callback){ 8 alert("我是母函數a"); 9 alert("如今要開始調用回調函數"); 10 callback(); 11 } 12 function b(){ 13 alert("我是回調函數b"); 14 } 15 function c(){ 16 alert("我是回調函數c"); 17 } 18 function d(){ 19 alert("我是回調函數d"); 20 } 21 function back(){ 22 a(b); 23 a(c); 24 a(d); 25 } 26 </script> 27 </head> 28 <body> 29 <button onclick="back()">點擊按鈕</button> 30 </body> 31 </html>
(3)、自調用函數
自調用函數也叫當即執行函數。使用關鍵字 function 定義一個函數,在給這個函數指定一個函數名,這叫函數聲明。使用關鍵字 function 定義一個函數,未給函數命名,在將這個匿名函數賦值個一個變量,這叫作函數表達式,這也是最多見的函數表達式語法。匿名函數就是使用關鍵字 function 定義一個函數,可是不給函數命名,匿名函數屬於函數表達式。匿名函數有不少做用,可賦予變量建立函數,賦予一個事件則稱爲事件處理程序。
函數聲明和函數表達式的區別:JS 引擎在解析 JS 代碼時當前執行環境中的函數聲明會提高,而函數表達式只能等到 JS 引擎執行到他所在的做用域時,纔會逐行的解析函數表達式。函數聲明不能使用自調用,而函數表達式可使用自調用。
函數的自調用就是在函數體後加括號,再用括號整個包起來。這樣說明該函數是一個函數表達式。
1 (function (a, b) { 2 alert(a * b); 3 }(2, 3)); //返回:6
(4)、構造函數
函數經過關鍵字 function 定義,也可使用關鍵字 new 定義。函數即對象,對象具備屬性和方法,構造函數就是將定義的函數做爲某個對象的屬性,函數定義做爲對象的屬性,則稱之爲對象方法。函數若是用於建立新的對象,就叫作對象的構造函數。
(5)、閉包
簡單理解就是:子函數可使用父函數中的局部變量。以前好幾個例子中都用到了閉包,就是 window.onload 函數下定義的點擊事件函數。
JS 的變量能夠是全局變量或局部變量,在函數以外聲明的變量就是全局變量,函數以內聲明的變量就是局部變量,私有變量能夠用到閉包。函數能夠訪問全局的變量,也能夠訪問局部的變量。做用域就是變量和函數的可訪問範圍,即做用域控制着變量和函數的可見性與生命週期,忽略塊級做用域,做用域可分爲全局做用域和局部做用域。全局變量是全局對象的屬性,局部變量是調用對象的屬性。全局變量屬於 window 對象,全局變量在任何地方均可以訪問,局部變量只能用於定義他的函數內部,這就是 JS 的做用域鏈,即內層函數能夠訪問外層函數的局部變量,外層函數不能訪問內層函數的局部變量。全局變量和局部變量即使名稱相同,他們也是兩個不一樣的變量。修改其中一個,不會修改另外一個的值。這裏須要注意:在函數內聲明的量,若是不使用關鍵字 var ,那麼他就是一個全局變量。
全部函數都能訪問全局變量,也就是全部的函數均可以訪問他上一層的做用域。JS 支持函數嵌套,嵌套函數能夠訪問上一層的函數變量。閉包就是能夠訪問上一層函數做用域中的變量函數,即使上一層函數已經關閉。
閉包實例解析:
若是想實現點擊按鈕計數,能夠聲明一個變量,並賦初始值爲 0,函數設置值加 1。可是這個全局變量在任何地方均可以使用,即使沒有調用這個函數,計數也會改變。
1 <body> 2 <input type="button" value="全局變量計數" onclick="show()"> 3 <input type="button" value="調用一次變量" onclick="change()"> 4 <p id="p1">0</p> 5 <script> 6 var num = 0; 7 function count() { 8 return num += 1; 9 } 10 var oP = document.getElementById("p1"); 11 function show(){ 12 oP.innerHTML = count(); 13 } 14 function change(){ 15 alert(num = 10); 16 } 17 </script> 18 </body>
上面例子,每次點擊按鈕計數正常,但若是調用一次變量,給變量賦值爲 10,再點按鈕將從 11 開始計數。那麼能夠將這個變量聲明在函數內,若是沒有調用這個函數,計數將不會改變。
1 <body> 2 <input type="button" value="點擊計數" onclick="show()"> 3 <p id="p1">0</p> 4 <script> 5 function count() { 6 var num = 0; 7 return num += 1; 8 } 9 var oP = document.getElementById("p1"); 10 function show(){ 11 oP.innerHTML = count(); 12 } 13 </script> 14 </body>
點擊按鈕能夠看到事與願違,雖然這樣不能在函數外部使用變量,也就不能修改計數,可是每次點擊按鈕值都爲 1。由於變量是在函數內聲明的,只有該函數可使用,每點擊按鈕一次,調用一次該函數,每次調用變量的初始值都爲 0,再加 1 就是 1。那麼使用 JS 的嵌套函數能夠完成這一問題,內嵌函數能夠訪問父函數的變量。
1 <body> 2 <input type="button" value="計數" onclick="show()"> 3 <p id="p1">0</p> 4 <script> 5 function count(){ 6 var num = 0; 7 function add(){ 8 num += 1; 9 } 10 add(); 11 return num; 12 } 13 add(); //報錯:未定義 14 function show(){ 15 document.getElementById("p1").innerHTML = count(); 16 } 17 </script> 18 </body>
雖然這樣能夠解決變量的問題,可是若是能夠在外部調用 add() 函數的話,那麼點擊按鈕計數就完美了,夢想老是美好的,現實倒是殘酷的,內嵌函數不能在外部被調用。這時候咱們的閉包就來了,咱們須要閉包,有了閉包這個問題就真的完美了。
1 <body> 2 <input type="button" value="計數" onclick="show()"> 3 <p id="p1">0</p> 4 <script> 5 var count = (function (){ 6 var num = 0; 7 return function (){ 8 return num += 1; 9 }; 10 }()); 11 var oP = document.getElementById('p1'); 12 function show(){ 13 oP.innerHTML = count(); 14 } 15 </script> 16 </body>
變量 count 指定了函數自我調用返回值,自我調用函數只執行一次,計數初始值爲 0,並返回函數表達式,計數受匿名函數做用域的保護,只能經過 count() 方法修改。
變量 count 能夠做爲一個函數使用,他能夠訪問函數上一層做用域的計數,這就叫作 JS 閉包,函數擁有本身的私有變量。