20. 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
複製程式碼
19. 鍵盤事件屬性
event.keyCode; // 獲取按下的鍵盤按鍵的鍵碼值(Unicode值)
event.ctrlKey; // 獲取是否按下了ctrl鍵
event.shiftKey; // 獲取是否按下了shift鍵
event.altKey; // 獲取是否按下了alt鍵
event.metaKey; // 獲取是否按下了meta鍵
複製程式碼
18. 滑鼠事件屬性
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 // 獲取指定事件上哪個鍵盤鍵或滑鼠按鈕被按下
複製程式碼
17. addEventListener 和 attachEvent 區別
attachEvent方法適用於IE
attachEvent中的事件帶on, 而addEventListener中的事件不帶on
attachEvent 方法有兩個引數:第一個引數為事件名稱,第二個引數為接收事件處理的函式; addEventListener 方法有三個引數:第一個引數為事件名稱(不含 on,如 "click"),第二個引數為要接收事件處理的函式,第三個引數為一個bool值,預設為false
1. 新增多個事件處理程式執行的順序不同
js程式碼(addEventListener):
var btn=document.getElementById("myBtn");
btn.addEventListener("click",function(){
alert(1);
},false);
btn.addEventListener("click",function(){
alert(2);
},false);
//執行結果 1 ,2
複製程式碼
js程式碼(attachEvent):
var btn=document.getElementById("myBtn");
btn.attachEvent("onclick",function(){
alert(1);
});
btn.attachEvent("onclick",function(){
alert(2);
});
//執行結果 2 ,1
複製程式碼
2. 事件處理程式的作用域不同
DOM2級事件新增的事件處理程式,它的作用域是所屬的元素,而IE的事件處理程式會在全域性作用域中執行。
js程式碼(addEventListener):
var btn=document.getElementById("myBtn");
btn.addEventListener("click",function(){
console.log(this.id); // myBtn
},false);
複製程式碼
js程式碼(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: 指定事件觸發時執行的函式
複製程式碼
16. addEventListener 和 on 區別
html程式碼:
<div id="box">addEventListener 和 on 區別</div>
複製程式碼
js程式碼:
window.onload = function(){
var box = document.getElementById("box");
box.onclick = function(){
console.log("我是box1");
}
box.onclick = function(){
console.log("我是box2");
}
}
//執行結果:“我是box2”
複製程式碼
js程式碼:
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可以多次繫結同一個事件並且不會覆蓋上一個事件。
15. HTML5 新增的事件
contextmenu事件
這個事件是當滑鼠右擊的時候觸發的,但是觸發這個屬性的時候預設的行為也會被觸發,所以需要通過preventDefault()方法來阻止。
beforeunload事件
beforeunload在頁面解除安裝之前觸發,該事件會彈出一個對話方塊,詢問是否確定離開。
hashchange事件
該事件當URL中的hash值改變時觸發,通常用於Ajax應用中利用URL引數儲存導航資訊;這個在前端路由的製作中是非常有用得。
14. 阻止事件預設行為和阻止事件冒泡
html程式碼:
<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 連結的跳轉行為和表單自動提交行為
js程式碼:
var prevent = document.getElementById("prevent");
prevent.addEventListener("click", function(event){
event.preventDefault();
}, false);
//使用preventDefault()方法就阻止了a標籤開啟新視窗的預設行為
複製程式碼
stopPropagation(): 用於阻止事件的進一步獲取和傳播;
比如:阻止事件繼續向上層冒泡
js程式碼:
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; //阻止事件的進一步獲取或者冒泡;
複製程式碼
使用示例
js程式碼:
function prevent(event) {
event = event || window.event;
if(event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
}
//使用 if else 去判斷
複製程式碼
13. 事件捕獲和事件冒泡
事件冒泡執行過程:從最具體的的元素(你單擊的那個元素)開始向上開始冒泡,下面的案例的順序是:content > wrap
事件捕獲執行過程:從最不具體的元素(最外面的那個盒子)開始向裡面冒泡,下面的案例的順序是:wrap > content
html程式碼:
<div id="wrap">
<div id="content"></div>
</div>
複製程式碼
js程式碼: (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
複製程式碼
js程式碼: (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,則按照事件捕獲的執行順序進行。
12. 給 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>
複製程式碼
11. 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 表示該值定義為空值。
10. 解決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);
});
複製程式碼
9. web應用整體效能的考慮
8 9兩點 參考於 《JavaScript DOM程式設計藝術(第2版)》
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>標記之前,就可以讓頁面變的更快。
8. 使你所寫的頁面能夠向後相容、平穩退化
針對這一問題的最簡單的解決方案是,檢測瀏覽器對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;
}
複製程式碼
7. 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'
複製程式碼
6. 在選中的元素上繫結事件和通過代理繫結事件的區別
在選中的元素上繫結click事件:
$('a').on('click', function(){});
複製程式碼
通過代理繫結click事件:
$(document).on('click', 'a', function(){});
複製程式碼
在選中的元素上繫結事件只能為頁面現有的a元素繫結點選事件,如果是動態生成的新的a元素是沒有事件的。
通過代理繫結事件是將指定的事件繫結在document上,新新增的a元素也能觸發此事件。
5. reload 方法,強迫瀏覽器重新整理當前頁面。
語法:location.reload([falseOrTrue]) ;
引數: falseOrTrue, 可選引數。 預設為 false,從客戶端快取裡取當前頁。true,則以 GET 方式,從服務端取最新的頁面,相當於客戶端點選 F5(“重新整理”)。
html程式碼:
<a href="javascript:location.reload();">點選重新整理頁面</a>
<span onclick="location.reload(true);">點選重新整理頁面</span>
複製程式碼
4. 禁止頁面選取內容
適用於IE、Chrome瀏覽器,在 head 的 <script> 標籤裡面新增 js 程式碼
js程式碼:
document.onselectstart = function (e) { return false; }
或者
document.onselectstart = new Function('event.returnValue = false;');
複製程式碼
在firefox火狐瀏覽器中,禁止元素被選取可以採用 CSS 樣式在來控制
CSS程式碼:
body{
-moz-user-focus: ignore;
-moz-user-input: disabled;
-moz-user-select: none;
}
複製程式碼
禁止滑鼠右鍵
js程式碼:
document.oncontextmenu = function(e){return false;}
複製程式碼
3. 正規表示式驗證
// 驗證是否為手機號
function phone(num) {
return /^1[34578]\d{9}$/.test(num);
}
// 驗證是否為郵箱
function email(e) {
return /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/.test(e);
}
複製程式碼
2. 返回頂部
js程式碼:
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;
});
複製程式碼
1. js 中 Error 錯誤
ReferenceError:作用域判別錯誤,通過作用域鏈的搜尋找不到相應的變數。
TypeError:可以通過作用域搜尋到變數,但是對變數的操作不合法。
SyntaxError:語法錯誤。