1. Call 和 Apply 的區別
語法:
function.call(thisObj [, arg1[, arg2[, [, ...argN]]]]);
function.apply(thisObj [, argArray] );
定義: call 和 apply 可以讓我們手動設置 this 指向
兩個參數: 第一個參數是 綁定 this 指向;第二個參數是 向將要執行的函數傳遞的參數
區別: 第二個參數, call 以一個一個的形式傳遞參數;apply 以數組的形式傳遞參數
var a = 10; function sum(num1, num2) { console.log(this.a + num1 + num2); } var obj = { a: 20 } sum(10, 10); //30 sum.call(obj, 10, 10); // 40 sum.apply(obj, [10, 10]); // 40
2. 鍵盤事件屬性
event.keyCode; // 獲取按下的鍵盤按鍵的鍵碼值(Unicode值) event.ctrlKey; // 獲取是否按下了ctrl鍵 event.shiftKey; // 獲取是否按下了shift鍵 event.altKey; // 獲取是否按下了alt鍵 event.metaKey; // 獲取是否按下了meta鍵
3. 鼠標事件屬性
event.screenX/event.screenY // 獲取鼠標基於屏幕的X軸/Y軸坐標 event.clientX/event.clientY // 獲取鼠標基於瀏覽器窗口的X軸/Y軸坐標 event.pageX/event.pageY // 獲取鼠標基於文檔的X軸/Y軸坐標 event.button // 獲取鼠標按下的鍵。非IE瀏覽器中0為鼠標左鍵,1為鼠標中鍵,2為鼠標右鍵 event.which // 獲取指定事件上哪個鍵盤鍵或鼠標按鈕被按下
4. addEventListener 和 attachEvent 區別
attachEvent方法適用於IE
attachEvent中的事件帶on, 而addEventListener中的事件不帶on
attachEvent 方法有兩個參數:第一個參數為事件名稱,第二個參數為接收事件處理的函數; addEventListener 方法有三個參數:第一個參數為事件名稱(不含 on,如 "click"),第二個參數為要接收事件處理的函數,第三個參數為一個bool值,默認為false
1. 添加多個事件處理程序執行的順序不同
addEventListener: var btn=document.getElementById("myBtn"); btn.addEventListener("click",function(){ alert(1); },false); btn.addEventListener("click",function(){ alert(2); },false); //執行結果 1 ,2
attachEvent: var btn=document.getElementById("myBtn"); btn.attachEvent("onclick",function(){ alert(1); }); btn.attachEvent("onclick",function(){ alert(2); }); //執行結果 2 ,1
2. 事件處理程序的作用域不同
DOM2級事件添加的事件處理程序,它的作用域是所屬的元素,而IE的事件處理程序會在全局作用域中運行。
addEventListener: var btn=document.getElementById("myBtn"); btn.addEventListener("click",function(){ console.log(this.id); // myBtn },false);
attachEvent: var btn=document.getElementById("myBtn"); btn.attachEvent("onclick",function(){ alert(this===window); // true });
3. 移除綁定事件 removeEventListener() 和 detachEvent()
移除 addEventListener 事件: element.removeEventListene(event, function, useCapture) event: 事件名,注意不使用“on”前綴,如 click function: 指定事件觸發時執行的函數 useCapture: 指定事件是否在捕獲或冒泡階段執行 true: 在捕獲階段執行 false: 在冒泡階段進行,默認值為false 如果添加時用的捕獲階段,那么在移除時也要用捕獲階段,否則無法移除它們 如果是同一個元素同一個調用函數同一個useCapture值綁定多次,在移除時只需要執行一次移除
移除 attachEvent 事件: element.detachEvent(event, function) event: 事件名,注意要使用“on”前綴,如 onclick function: 指定事件觸發時執行的函數
5. addEventListener 和 on 區別
<div id="box">addEventListener 和 on 區別</div>
window.onload = function(){ var box = document.getElementById("box"); box.onclick = function(){ console.log("我是box1"); } box.onclick = function(){ console.log("我是box2"); } } //運行結果:“我是box2”
window.onload = function(){ var box = document.getElementById("box"); box.addEventListener("click", function(){ console.log("我是box1"); }) box.addEventListener("click", function(){ console.log("我是box2"); }) } 運行結果:我是box1 我是box2
第二個onclick會把第一個onclick給覆蓋了,雖然大部分情況我們用on就可以完成我們想要的結果,但是有時我們又需要執行多個相同的事件,很明顯如果用on完成不了我們想要的,而addEventListener可以多次綁定同一個事件並且不會覆蓋上一個事件。
6. HTML5 新增的事件
contextmenu事件
這個事件是當鼠標右擊的時候觸發的,但是觸發這個屬性的時候默認的行為也會被觸發,所以需要通過preventDefault()方法來阻止。
beforeunload事件
beforeunload在頁面卸載之前觸發,該事件會彈出一個對話框,詢問是否確定離開。
hashchange事件
該事件當URL中的hash值改變時觸發,通常用於Ajax應用中利用URL參數保存導航信息;這個在前端路由的制作中是非常有用得。
7. 阻止事件默認行為和阻止事件冒泡
<div id="wrap" style="width: 200px; height: 200px; background: gray;"> <div id="btn" style="width: 100px; height: 100px; background: orangered;"></div> <a id="prevent" target="_blank" href="http://www.baidu.com">preventDefault</a> </div>
標准瀏覽器的使用方法
preventDefault(): 用於阻止事件的默認行為;
比如: a 鏈接的跳轉行為和表單自動提交行為
var prevent = document.getElementById("prevent"); prevent.addEventListener("click", function(event){ event.preventDefault(); }, false); //使用preventDefault()方法就阻止了a標簽打開新窗口的默認行為
stopPropagation(): 用於阻止事件的進一步獲取和傳播;
比如:阻止事件繼續向上層冒泡
var btn = document.getElementById("btn"), wrap= document.getElementById("wrap"); btn.addEventListener("click",function(event){ alert("btn"); event.stopPropagation(); },false); wrap.addEventListener("click",function(){ alert("wrap"); },false); //點擊btn時,這樣就阻止了id="btn"向上級id="wrap"冒泡,打印出來的結果是:彈窗僅彈出btn。否則,將會先彈出btn,然后彈出wrap。
低版本IE瀏覽器的使用方法
event.returnValue = false; //阻止事件的默認行為; event.cancelBubble = true; //阻止事件的進一步獲取或者冒泡;
示例
function prevent(event) { event = event || window.event; if(event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; } } //使用 if else 去判斷
8. 事件捕獲和事件冒泡
事件冒泡執行過程:從最具體的的元素(你單擊的那個元素)開始向上開始冒泡,下面的案例的順序是:content > wrap
事件捕獲執行過程:從最不具體的元素(最外面的那個盒子)開始向里面冒泡,下面的案例的順序是:wrap > content
<div id="wrap"> <div id="content"></div> </div>
(addEventListener第三個參數寫的是false, 默認為false) window.onload = function(){ var wrap= document.getElementById("wrap"); var content= document.getElementById("content"); wrap.addEventListener("click", function(){ console.log("我是wrap"); }, false) content.addEventListener("click", function(){ console.log("我是content"); }) } 運行結果:我是content 我是wrap
(addEventListener第三個參數寫的是true, 默認為false) window.onload = function(){ var wrap= document.getElementById("wrap"); var content= document.getElementById("content"); wrap.addEventListener("click", function(){ console.log("我是wrap"); }, true) content.addEventListener("click", function(){ console.log("我是content"); }) } 運行結果:我是wrap 我是content
第三個參數寫的是true,則按照事件捕獲的執行順序進行。
9. 給 select 標簽 option 內容加鏈接
<select onchange="window.open(options[selectedIndex].value, '_self')"> <option value="http://www.bj-hmk.com/">中文</option> <option value="http://en.bj-hmk.com/">English</option> </select>
10. Null 和 Undefined
undefined 表示根本不存在定義
null 表示一個值被定義了,定義為“空值”
(1)變量被聲明了,但沒有賦值時,就等於undefined。
(2)調用函數時,應該提供的參數沒有提供,該參數等於undefined。
(3)對象沒有賦值的屬性,該屬性的值為undefined。
(4)函數沒有返回值時,默認返回undefined。
所以設置一個值為 null 是合理的,如
objA.valueA = null;但設置一個值為 undefined 是不合理的,如
objA.valueA = undefined; // 應該直接使用 delete objA.valueA; 任何一個存在引用的變量值為undefined都是一件錯誤的事情。
這樣判斷一個值是否存在,就可以用
objA.valueA === undefined // 不應使用 null 因為 undefined == null,而 null 表示該值定義為空值。
11. 解決slideDown()和slideUp()鼠標快速移入移出,出現反復執行的問題
方法一: $(".orderDivMain").hover(function () { if (!$(".orderDivId").is(":animated")) { $(this).find('.orderDivId').slideDown(500); } }, function () { if (!$(".orderDivId").is(":animated")) { $(this).find('.orderDivId').slideUp(500); } }); 方法二: $(".orderDivMain").hover(function () { $(".orderDivId").slideDown(500); }); $(".orderDivId").mouseleave(function () { $(".orderDivId").slideUp(500); });
12. web應用整體性能的考慮
12 13兩點 參考於 《JavaScript DOM編程藝術(第2版)》
盡量少訪問DOM和盡量減少標記
if(document.getElementsByTagName("a").length > 0){ var links = document.getElementsByTagName("a"); for(var i = 0; i < links.length; i++){ something... } }
上面這段代碼使用了兩次getElementsByTagName方法去執行相同的操作,浪費了一次搜索。更好的辦法是把第一次搜索的結果保存在一個變量中,然后重用該結果:
var links = document.getElementsByTagName("a"); if(links.length > 0){ for(var i = 0; i < links.length; i++){ something... } }
合並和放置腳本
<script src="js/functionA.js"></script> <script src="js/functionB.js"></script> <script src="js/functionC.js"></script>
<script src="js/function.js"></script>
上面兩種做法,推薦的做法是把第一種functionA.js、functionB.js、functionC.js合並到一個腳本文件中。這樣就可以減少加載頁面時發送的請求數量,而減少請求數量通常都是性能優化時首先要考慮的。
位於<head>塊中的腳本會導致瀏覽器無法並行加載其他文件,把<script>標簽放在</body>標記之前,就可以讓頁面變的更快。
13. 使你所寫的頁面能夠向后兼容、平穩退化
針對這一問題的最簡單的解決方案是,檢測瀏覽器對javascript的支持程度,即對象檢測。幾乎所有的東西(包括各種方法在內)都可以被當作對象來對待,這意味着我們可以很容易的把不支持某個特定的DOM方法的瀏覽器檢測出來:
if(method){ statements }
例如,檢測瀏覽器是否支持getElementById方法:
if(document.getElementById){ statements using getElementById }
但是如果需要檢測多個DOM方法或者屬性是否存在,那么最重要的語句可能會被深埋在一層又一層的花括號里,使得代碼將會很難閱讀和理解。
那么就可以把測試的條件改為“如果你不理解這個方法,請離開”則會變得簡單明了。
if(!document.getElementById){ return false; }
若需要測試多個方法或屬性是否支持,可以使用“邏輯或”操作符將其合並:
if(!document.getElementById || !document.getElementsByTagName){ return false; }
14. jQuery中attr和prop的區別
處理HTML元素本身就帶有的固有屬性時使用prop方法
處理HTML元素我們自己定義的Dom屬性時使用attr方法
<input class='check1' type='checkbox'>選擇1 <input class='check2' type='checkbox' checked>選擇2
checked屬於checkbox元素的固有屬性,讓我們來看看prop和attr的結果有什么不同:
prop方法: $('.check1').prop('checked') -- false $('.check2').prop('checked') -- true
attr方法: $('.check1').attr('checked') -- undefined $('.check2').attr('checked') -- 'checked'
15. 在選中的元素上綁定事件和通過代理綁定事件的區別
在選中的元素上綁定click事件: $('a').on('click', function(){});
通過代理綁定click事件: $(document).on('click', 'a', function(){});
在選中的元素上綁定事件只能為頁面現有的a元素綁定點擊事件,如果是動態生成的新的a元素是沒有事件的。
通過代理綁定事件是將指定的事件綁定在document上,新添加的a元素也能觸發此事件。
16. reload 方法,強迫瀏覽器刷新當前頁面。
語法:location.reload([falseOrTrue]) ;
參數: falseOrTrue, 可選參數。 默認為 false,從客戶端緩存里取當前頁。true,則以 GET 方式,從服務端取最新的頁面,相當於客戶端點擊 F5(“刷新”)。
<a href="javascript:location.reload();">點擊刷新頁面</a> <span onclick="location.reload(true);">點擊刷新頁面</span>
17. 禁止頁面選取內容
適用於IE、Chrome瀏覽器,在 head 的 <script> 標簽里面添加 js 代碼
document.onselectstart = function (e) { return false; } 或者 document.onselectstart = new Function('event.returnValue = false;');
在firefox火狐瀏覽器中,禁止元素被選取可以采用 CSS 樣式在來控制
body{ -moz-user-focus: ignore; -moz-user-input: disabled; -moz-user-select: none; }
禁止鼠標右鍵
document.oncontextmenu = function(e){return false;}
18. 正則表達式驗證
// 驗證是否為手機號 function phone(num) { return /^1[34578]\d{9}$/.test(num); } // 驗證是否為郵箱 function email(e) { return /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/.test(e); }
19. 返回頂部
window.onscroll = function () { if (document.body.scrollTop || document.documentElement.scrollTop > 0) { document.getElementById('back_top').style.display = "block"; } else { document.getElementById('back_top').style.display = "none"; } } $('.back_top').click(function () { $("html,body").animate({ scrollTop: 0 }, 500); return false; });
20. js 中 Error 錯誤
ReferenceError:作用域判別錯誤,通過作用域鏈的搜尋找不到相應的變量。
TypeError:可以通過作用域搜索到變量,但是對變量的操作不合法。
SyntaxError:語法錯誤。