1.利用冒泡和不利用冒泡的差別
答案:
1.綁定位置不同:不利用冒泡綁定在目標元素上,利用冒泡綁定在父元素上.
2.監聽對象的個數不同:不利用冒泡會反復創建多個監聽,利用冒泡始終只有
一個監聽.
3.動態生成元素:不利用冒泡無法自動獲得事件處理函數,必須反復綁定
利用冒泡可讓動態添加的子元素自動獲得父元素的處理函數,無需反復綁定.
2.按HTML查找和按選擇器查找的差別
答案:
1.返回值不同:按HTML查找返回動態集合,按選擇器查找返回非動態集合
2.效率不同:按HTML查找效率高,按選擇器查找效率低
3.易用性不同:當條件復雜時,按HTML查找繁瑣,而按選擇器查找簡單
3.列舉DOM中常用優化
答案:
1.查找時,如果只用一個條件就可查詢出結果時,優先選擇易用的按選擇器查找.
2.添加時,盡量減少操作DOM樹的次數,減少重排重繪。如果同時添加父元素和子元素,
應先將子元素添加到父元素,最后再將父元素添加到DOM樹。如果添加多個平級子元素,
則應先將子元素添加到文檔片段,最后,再將文檔片段添加到DOM樹.
3.修改時,盡量減少重排重繪。如果同時修改多個元素的內容和樣式。應使用class批量修改樣式.
4.事件綁定時,應盡量利用冒泡減少事件監聽的個數.
4.如何鑒別瀏覽器的名稱和版本號
答案:
var browser,version,ua=navigator.userAgent;
if(ua.indexOf("IE")!=-1) browser="IE"
else if(ua.indexOf("Edge")!=-1) browser="Edge"
else if(ua.indexOf("Firefox")!=-1) browser="Firefox"
else if(ua.indexOf("OPR")!=-1) browser="OPR"
else if(ua.indexOf("Chrome")!=-1) browser="Chrome"
else if(ua.indexOf("Safari")!=-1) browser="Safari"
else if(ua.indexOf("Trident")!=-1) browser="IE",version=11;
document.write(`<h1>${browser}</h1>`);
if(version===undefined){
//截取: 從瀏覽器名稱所在位置,再跳過瀏覽器名稱長度+1 之后的3位
var i=ua.indexOf(browser);
i+=browser.length+1;
version=parseFloat(ua.slice(i,i+3))
}
document.write(`<h1>${version}</h1>`);
5.為按鈕綁定事件,實現事件節流:
答案:
//節流
var canClick=true;
btn.onclick=function(){
if(canClick){
canClick=false;
consoe.log("發送ajax請求,加載更多...");
setTimeout(function(){
console.log("請求完成!");
canClick=true;
},3000)
}
}
6.為頁面綁定滾動事件,實現事件防抖:
答案:
//防抖
var timer1;
window.onscroll=function(){
if(timer1!==undefined){
clearTimeout(timer1);
}
timer1=setTimeout(function(){
console.log("發送ajax請求,加載更多");
timer1=undefined;
},200)
}
7.DOM元素e的e.getAttribute(propName)和e.propName有什么區別和聯系?
答案:
e.getAttribute(),是標准DOM操作文檔元素屬性的方法,具有通用性可在任意
文檔上使用,返回元素在源文件中設置的屬性
e.propName通常是在HTML文檔中訪問特定元素的特性,瀏覽器解析元素后生成
對應對象(如 a標簽生成HTMLAnchorElement),這些對象的特性會根據特定規則
結合屬性設置得到,對於對應特性的屬性,只能使用getAtrribute進行訪問
- e.getAttribute()返回值是源文件中設置的值,類型是字符串或者 null(有的實現返回"")
- e.propName 返回值可能是字符串、布爾值、對象、undefined 等
- 大部分 attribute 與 property 是一一對應關系,修改其中一個會影響另一個,如 id,title 等屬性
- 一些布爾屬性`<input hidden/>`的檢測設置需要 hasAttribute 和 removeAttribute 來完成,或者設置對應 property
- 像`<a href="../index.html">link</a>`中 href 屬性,轉換成 property 的時候需要通過轉換得到完整 URL
- 一些 attribute 和 property 不是一一對應如:form 控件中`<input value="hello"/>`對應的是 defaultValue,修改或設置 value property 修改的是控件當前值,setAttribute 修改 value 屬性不會改變 value property
8.如何最小化重繪(repaint)和回流(reflow)?
答案:
- 需要對元素進行復雜擦歐洲哦時,可以先隱藏(display:"none"),操作完成后再顯示.
- 需要創建多個DOM節點時,使用DocumentFragment創建完之后一次性的加入documnet
- 緩存Layout屬性值,如:var left =elem.offsetLeft;
這樣,多次使用left產生一次回流
- 盡量避免用table布局(table元素一旦觸發回流就會導致table里所有的其他元素回流)
- 避免使用css表達式(expression),因為每次調用都會重新計算值(包括加載頁面)
- 盡量使用css屬性簡寫,如:用border代替border-width,border-style,border-color
- 批量修改元素樣式:elem.style.xxx
9.描述一下DOM事件模型:
答案:捕獲、目標觸發、冒泡
捕獲階段:由外向內,依次記錄各級父元素上的事件處理函數。
只記錄,暫不觸發。
目標觸發:優先觸發目標元素上的事件處理函數。
冒泡:由內向外,依次觸發各級父元素上的事件處理函數.
10.談談事件委托/代理:
答案:事件委托是指將事件綁定目標元素的父元素上,利用冒泡機制觸發該事件.
優點:
- 可以減少事件注冊,節省大量內存占用
- 可以將事件應用於動態添加的子元素上
缺點:使用不當會造成事件在不應該觸發時觸發
示例:
js
url.addEventListener('click',function(e){
var target =event.target || event.srcElement;
if(!!target && target.nodeName.toUpperCase() === "LI"){
console.log(target.innerHTML);
}
},false);
11.IE的事件處理和W3C的事件處理有哪些區別?
答:
綁定事件
- W3C: targetEl.addEventListener('click', handler, false);
- IE: targetEl.attachEvent('onclick', handler);
刪除事件
- W3C: targetEl.removeEventListener('click', handler, false);
- IE: targetEl.detachEvent(event, handler);
事件對象
- W3C: var e = arguments.callee.caller.arguments[0]
- IE: window.event
事件目標
- W3C: e.target
- IE:window.event.srcElement
阻止事件默認行為
- W3C:e.preventDefault()
- IE:window.event.returnValue =false
阻止事件傳播
- W3C:e.stopPropagation()
- IE:window.event.cancelBubble = true
12.前端優化的方法:
答案:
1.減少dom操作
2.部署前,圖片壓縮,代碼壓縮
3.優化js代碼結構,減少冗余代碼
4.減少HTTP請求,合理設置HTTP緩存
5.使用內容分發cdn加速
6.靜態資源緩存
7.圖片延遲加載