Web前端面試題目匯總
閱讀目錄
- HTML/CSS部分
- JavaScript部分
- HTTP
- 演算法相關
- Web安全
- 前端性能
- 設計模式
- 正則表達式
- 職業規劃
以下是收集一些面試中經常會遇到的經典面試題以及自己面試過程中有一些未解決的問題,通過對知識的整理以及經驗的總結,重新鞏固自身的前端基礎知識,如有錯誤或更好的答案,歡迎指正,水平有限,望各位不吝指教。:)
一、HTML/CSS部分
1、什麼是盒子模型?
在網頁中,一個元素佔有空間的大小由幾個部分構成,其中包括元素的內容(content),元素的內邊距(padding),元素的邊框(border),元素的外邊距(margin)四個部分。這四個部分佔有的空間中,有的部分可以顯示相應的內容,而有的部分只用來分隔相鄰的區域或區域。4個部分一起構成了css中元素的盒模型。
2、行內元素有哪些?塊級元素有哪些? 空(void)元素有那些?
行內元素:a、b(粗體)、span、img、input、strong(強調文本)、select、label、em(強調文本、button、textarea
塊級元素:div、ul、li、dl、dt、dd、p、h1-h6、blockquote(標記)
空元素:即系沒有內容的HTML元素,例如:br、meta、hr、link、input、img
3、CSS實現垂直水平居中
一道經典的問題,實現方法有很多種,以下是其中一種實現:
HTML結構:<div class="wrapper">
<div class="content"></div>
</div>
CSS:
.wrapper {
position: relative;
width: 500px;
height: 500px;
background-color: #ddd;
}
.content{
background-color:#6699FF;
width:200px;
height:200px;
position: absolute; //父元素需要相對定位
top: 50%;
left: 50%;
margin-top:-100px ; //二分之一的height,width
margin-left: -100px;
}
4、什麼是CSS Hack?
一般來說是針對不同的瀏覽器寫不同的CSS,就是 CSS Hack。IE瀏覽器Hack一般又分為三種,條件Hack、屬性級Hack、選擇符Hack(詳細參考CSS文檔:css文檔)。例如:
// 1、條件Hack
<!--[if IE]>
<style>
.test{color:red;}
</style>
<![endif]-->
// 2、屬性Hack
.test{
color:#0909; /* For IE8+ */
*color:#f00; /* For IE7 and earlier */
_color:#ff0; /* For IE6 and earlier */
}
// 3、選擇符Hack
* html .test{color:#090;} /* For IE6 and earlier */
* + html .test{color:#ff0;} /* For IE7 */
5、簡述同步和非同步的區別
同步是阻塞模式,非同步是非阻塞模式。
同步就是指一個進程在執行某個請求的時候,若該請求需要一段時間才能返回信息,那麼這個進程將會一直等待下去,直到收到返回信息才繼續執行下去;
非同步是指進程不需要一直等下去,而是繼續執行下面的操作,不管其他進程的狀態。當有消息返回時系統會通知進程進行處理,這樣可以提高執行的效率。6、px和em的區別
px和em都是長度單位,區別是,px的值是固定的,指定是多少就是多少,計算比較容易。em得值不是固定的,並且em會繼承父級元素的字體大小。
瀏覽器的默認字體高都是16px。所以未經調整的瀏覽器都符合: 1em=16px。那麼12px=0.75em, 10px=0.625em7、什麼叫優雅降級和漸進增強?
漸進增強 progressive enhancement:
針對低版本瀏覽器進行構建頁面,保證最基本的功能,然後再針對高級瀏覽器進行效果、交互等改進和追加功能達到更好的用戶體驗。優雅降級 graceful degradation:
一開始就構建完整的功能,然後再針對低版本瀏覽器進行兼容。區別:
a. 優雅降級是從複雜的現狀開始,並試圖減少用戶體驗的供給
b. 漸進增強則是從一個非常基礎的,能夠起作用的版本開始,並不斷擴充,以適應未來環境的需要
c. 降級(功能衰減)意味著往回看;而漸進增強則意味著朝前看,同時保證其根基處於安全地帶
8、瀏覽器的內核分別是什麼?
IE: trident內核
Firefox:gecko內核Safari:webkit內核Opera:以前是presto內核,Opera現已改用Google Chrome的Blink內核Chrome:Blink(基於webkit,Google與Opera Software共同開發)二、JavaScript部分
怎樣添加、移除、移動、複製、創建和查找節點?
1)創建新節點
createDocumentFragment() //創建一個DOM片段createElement() //創建一個具體的元素
createTextNode() //創建一個文本節點2)添加、移除、替換、插入
appendChild() //添加removeChild() //移除replaceChild() //替換insertBefore() //插入3)查找
getElementsByTagName() //通過標籤名稱getElementsByName() //通過元素的Name屬性的值getElementById() //通過元素Id,唯一性
實現一個函數clone,可以對JavaScript中的5種主要的數據類型(包括Number、String、Object、Array、Boolean)進行值複製。
/** * 對象克隆 * 支持基本數據類型及對象 * 遞歸方法 */function clone(obj) { var o; switch (typeof obj) { case "undefined": break; case "string": o = obj + ""; break; case "number": o = obj - 0; break; case "boolean": o = obj; break; case "object": // object 分為兩種情況 對象(Object)或數組(Array) if (obj === null) { o = null; } else { if (Object.prototype.toString.call(obj).slice(8, -1) === "Array") { o = []; for (var i = 0; i < obj.length; i++) { o.push(clone(obj[i])); } } else { o = {}; for (var k in obj) { o[k] = clone(obj[k]); } } } break; default: o = obj; break; } return o;}
如何消除一個數組裡面重複的元素?
// 方法一:var arr1 =[1,2,2,2,3,3,3,4,5,6], arr2 = [];for(var i = 0,len = arr1.length; i< len; i++){ if(arr2.indexOf(arr1[i]) < 0){ arr2.push(arr1[i]); }}document.write(arr2); // 1,2,3,4,5,6
在Javascript中什麼是偽數組?如何將偽數組轉化為標準數組?
偽數組(類數組):無法直接調用數組方法或期望length屬性有什麼特殊的行為,但仍可以對真正數組遍歷方法來遍歷它們。典型的是函數的argument參數,還有像調用getElementsByTagName,document.childNodes之類的,它們都返回NodeList對象都屬於偽數組。可以使用Array.prototype.slice.call(fakeArray)將數組轉化為真正的Array對象。
function log(){ var args = Array.prototype.slice.call(arguments); //為了使用unshift數組方法,將argument轉化為真正的數組 args.unshift((app)); console.log.apply(console, args);};
Javascript中callee和caller的作用?
caller是返回一個對函數的引用,該函數調用了當前函數;
callee是返回正在被執行的function函數,也就是所指定的function對象的正文。
請描述一下cookies,sessionStorage和localStorage的區別
sessionStorage用於本地存儲一個會話(session)中的數據,這些數據只有在同一個會話中的頁面才能訪問並且當會話結束後數據也隨之銷毀。因此sessionStorage不是一種持久化的本地存儲,僅僅是會話級別的存儲。而localStorage用於持久化的本地存儲,除非主動刪除數據,否則數據是永遠不會過期的。
web storage和cookie的區別
Web Storage的概念和cookie相似,區別是它是為了更大容量存儲設計的。Cookie的大小是受限的,並且每次你請求一個新的頁面的時候Cookie都會被發送過去,這樣無形中浪費了帶寬,另外cookie還需要指定作用域,不可以跨域調用。
除此之外,Web Storage擁有setItem,getItem,removeItem,clear等方法,不像cookie需要前端開發者自己封裝setCookie,getCookie。但是Cookie也是不可以或缺的:Cookie的作用是與伺服器進行交互,作為HTTP規範的一部分而存在 ,而Web Storage僅僅是為了在本地「存儲」數據而生。統計字元串中字母個數或統計最多字母數。
var str = "aaaabbbccccddfgh";var obj = {};for(var i=0;i<str.length;i++){ var v = str.charAt(i); if(obj[v] && obj[v].value == v){ obj[v].count = ++ obj[v].count; }else{ obj[v] = {}; obj[v].count = 1; obj[v].value = v; }}for(key in obj){ document.write(obj[key].value +=+obj[key].count+ ); // a=4 b=3 c=4 d=2 f=1 g=1 h=1 }
JavaScript基礎數據類型
JavaScript數據類型包括原始類型和引用類型,原始類型有五個:
Number(數值) String(字元串) Boolean(布爾) Null(空) Undefined(未定義)
引用類型有一個:
Object(對象)
通過typeof(x)可以返回一個變數x的數據類型「number」、「string」、「boolean」、「undefined」、」object」,這裡要注意一點:typeof運算符對於null類型返回的是object。
^ 《JavaScript高級程序設計》:
這實際上是JavaScript最初實現中的一個錯誤,後來被ECMAScript沿用了。現在null被認為是對象的佔位符,從而解釋了這一矛盾。但是從技術上來說,它仍然是原始值。談一談JavaScript作用域鏈
當執行一段JavaScript代碼(全局代碼或函數)時,JavaScript引擎會創建為其創建一個作用域又稱為執行上下文(Execution Context),在頁面載入後會首先創建一個全局的作用域,然後每執行一個函數,會建立一個對應的作用域,從而形成了一條作用域鏈。每個作用域都有一條對應的作用域鏈,鏈頭是全局作用域,鏈尾是當前函數作用域。
作用域鏈的作用是用於解析標識符,當函數被創建時(不是執行),會將this、arguments、命名參數和該函數中的所有局部變數添加到該當前作用域中,當JavaScript需要查找變數X的時候(這個過程稱為變數解析),它首先會從作用域鏈中的鏈尾也就是當前作用域進行查找是否有X屬性,如果沒有找到就順著作用域鏈繼續查找,直到查找到鏈頭,也就是全局作用域鏈,仍未找到該變數的話,就認為這段代碼的作用域鏈上不存在x變數,並拋出一個引用錯誤(ReferenceError)的異常。
如何理解JavaScript原型鏈
JavaScript中的每個對象都有一個prototype屬性,我們稱之為原型,而原型的值也是一個對象,因此它也有自己的原型,這樣就串聯起來了一條原型鏈,原型鏈的鏈頭是object,它的prototype比較特殊,值為null。
原型鏈的作用是用於對象繼承,函數A的原型屬性(prototype property)是一個對象,當這個函數被用作構造函數來創建實例時,該函數的原型屬性將被作為原型賦值給所有對象實例,比如我們新建一個數組,數組的方法便從數組的原型上繼承而來。
當訪問對象的一個屬性時, 首先查找對象本身, 找到則返回; 若未找到, 則繼續查找其原型對象的屬性(如果還找不到實際上還會沿著原型鏈向上查找, 直至到根). 只要沒有被覆蓋的話, 對象原型的屬性就能在所有的實例中找到,若整個原型鏈未找到則返回undefined;
如何理解類的閉包/創建/繼承?
閉包
官方」的解釋是:閉包是一個擁有許多變數和綁定了這些變數的環境的表達式(通常是一個函數),因而這些變數也是該表達式的一部分。
相信很少有人能直接看懂這句話,因為他描述的太學術。其實這句話通俗的來說就是:JavaScript中所有的function都是一個閉包。不過一般來說,嵌套的function所產生的閉包更為強大,也是大部分時候我們所謂的「閉包」。看下面這段代碼:function a() { var i = 0; function b() { alert(++i); } return b;}var c = a();c();
這段代碼有兩個特點:
1、函數b嵌套在函數a內部;
2、函數a返回函數b。
引用關係如圖:
這樣在執行完var c=a()後,變數c實際上是指向了函數b,再執行c()後就會彈出一個窗口顯示i的值(第一次為1)。這段代碼其實就創建了一個閉包,為什麼?因為函數a外的變數c引用了函數a內的函數b,就是說:
當函數a的內部函數b被函數a外的一個變數引用的時候,就創建了一個閉包。
讓我們說的更透徹一些。所謂「閉包」,就是在構造函數體內定義另外的函數作為目標對象的方法函數,而這個對象的方法函數反過來引用外層函數體中的臨時變數。這使得只要目標 對象在生存期內始終能保持其方法,就能間接保持原構造函數體當時用到的臨時變數值。儘管最開始的構造函數調用已經結束,臨時變數的名稱也都消失了,但在目 標對象的方法內卻始終能引用到該變數的值,而且該值只能通這種方法來訪問。即使再次調用相同的構造函數,但只會生成新對象和方法,新的臨時變數只是對應新 的值,和上次那次調用的是各自獨立的。
sessionStorage 、localStorage 和 cookie 之間的區別
1.cookie:存儲在用戶本地終端上的數據。有時也用cookies,指某些網站為了辨別用戶身份,進行session跟蹤而存儲在本地終端上的數據,通常經過加密。一般應用最典型的案列就是判斷註冊用戶是否已經登過該網站。
2.HTML5 提供了兩種在客戶端存儲數據的新方法:(HTML 5 Web 存儲)...兩者都是僅在客戶端(即瀏覽器)中保存,不參與和伺服器的通信;
- localStorage - 沒有時間限制的數據存儲,第二天、第二周或下一年之後,數據依然可用。
- sessionStorage - 針對一個 session 的數據存儲,當用戶關閉瀏覽器窗口後,數據會被刪除。
3、區別
共同點:都是保存在瀏覽器端,且同源的。
區別:cookie數據始終在同源的http請求中攜帶(即使不需要),即cookie在瀏覽器和伺服器間來回傳遞;cookie數據還有路徑(path)的概念,可以限制cookie只屬於某個路徑下。存儲大小限制也不同,cookie數據不能超過4k,同時因為每次http請求都會攜帶cookie,所以cookie只適合保存很小的數據,如會話標識。
而sessionStorage和localStorage不會自動把數據發給伺服器,僅在本地保存。sessionStorage和localStorage 雖然也有存儲大小的限制,但比cookie大得多,可以達到5M或更大。
數據有效期不同,sessionStorage:僅在當前瀏覽器窗口關閉前有效,自然也就不可能持久保持;localStorage:始終有效,窗口或瀏覽器關閉也一直保存,因此用作持久數據;cookie只在設置的cookie過期時間之前一直有效,即使窗口或瀏覽器關閉。
作用域不同,sessionStorage不在不同的瀏覽器窗口中共享,即使是同一個頁面;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。Web Storage 支持事件通知機制,可以將數據更新的通知發送給監聽者。Web Storage 的 api 介面使用更方便。
跨域請求資源的方法有哪些?
談談垃圾回收機制方式及內存管理
開發過程中遇到的內存泄露情況,如何解決的?
原生js發送ajax請求一般經歷哪些步驟
說說get和post請求的區別
1. get是從伺服器上獲取數據,post是向伺服器傳送數據。
2. get是把參數數據隊列加到提交表單的ACTION屬性所指的URL中,值和表單內各個欄位一一對應,在URL中可以看到。post是通過HTTP post機制,將表單內各個欄位與其內容放置在HTML HEADER內一起傳送到ACTION屬性所指的URL地址。用戶看不到這個過程。
3. 對於get方式,伺服器端用Request.QueryString獲取變數的值,對於post方式,伺服器端用Request.Form獲取提交的數據。
4. get傳送的數據量較小,不能大於2KB。post傳送的數據量較大,一般被默認為不受限制。但理論上,IIS4中最大量為80KB,IIS5中為100KB。
5. get安全性非常低,post安全性較高。但是執行效率卻比Post方法好。
建議:
1、get方式的安全性較Post方式要差些,包含機密信息的話,建議用Post數據提交方式;
2、在做數據查詢時,建議用Get方式;而在做數據添加、修改或刪除時,建議用Post方式。
三、HTTP
一次完整的HTTP事務是怎樣的一個過程?
基本流程:
a. 域名解析
b. 發起TCP的3次握手
c. 建立TCP連接後發起http請求
d. 伺服器端響應http請求,瀏覽器得到html代碼
e. 瀏覽器解析html代碼,並請求html代碼中的資源
f. 瀏覽器對頁面進行渲染呈現給用戶
HTTP的狀態碼有哪些?
HTTPS是如何實現加密?
四、演算法相關
手寫數組快速排序
關於快排演算法的詳細說明,可以參考阮一峰老師的文章快速排序
"快速排序"的思想很簡單,整個排序過程只需要三步:(1)在數據集之中,選擇一個元素作為"基準"(pivot)。(2)所有小於"基準"的元素,都移到"基準"的左邊;所有大於"基準"的元素,都移到"基準"的右邊。(3)對"基準"左邊和右邊的兩個子集,不斷重複第一步和第二步,直到所有子集只剩下一個元素為止。參考代碼: var quickSort = function(arr) { if (arr.length <= 1) { return arr; } var pivotIndex = Math.floor(arr.length / 2); var pivot = arr.splice(pivotIndex, 1)[0]; var left = []; var right = []; for (var i = 0; i < arr.length; i++){ if (arr[i] < pivot) { left.push(arr[i]); } else { right.push(arr[i]); } } return quickSort(left).concat([pivot], quickSort(right));};
JavaScript實現二分法查找
二分法查找,也稱折半查找,是一種在有序數組中查找特定元素的搜索演算法。查找過程可以分為以下步驟:
(1)首先,從有序數組的中間的元素開始搜索,如果該元素正好是目標元素(即要查找的元素),則搜索過程結束,否則進行下一步。(2)如果目標元素大於或者小於中間元素,則在數組大於或小於中間元素的那一半區域查找,然後重複第一步的操作。(3)如果某一步數組為空,則表示找不到目標元素。參考代碼: // 非遞歸演算法 function binary_search(arr, key) { var low = 0, high = arr.length - 1; while(low <= high){ var mid = parseInt((high + low) / 2); if(key == arr[mid]){ return mid; }else if(key > arr[mid]){ low = mid + 1; }else if(key < arr[mid]){ high = mid -1; }else{ return -1; } } }; var arr = [1,2,3,4,5,6,7,8,9,10,11,23,44,86]; var result = binary_search(arr,10); alert(result); // 9 返回目標元素的索引值
// 遞歸演算法 function binary_search(arr,low, high, key) { if (low > high){ return -1; } var mid = parseInt((high + low) / 2); if(arr[mid] == key){ return mid; }else if (arr[mid] > key){ high = mid - 1; return binary_search(arr, low, high, key); }else if (arr[mid] < key){ low = mid + 1; return binary_search(arr, low, high, key); } }; var arr = [1,2,3,4,5,6,7,8,9,10,11,23,44,86]; var result = binary_search(arr, 0, 13, 10); alert(result); // 9 返回目標元素的索引值
五、Web安全
你所了解到的Web攻擊技術
(1)XSS(Cross-Site Scripting,跨站腳本攻擊):指通過存在安全漏洞的Web網站註冊用戶的瀏覽器內運行非法的HTML標籤或者JavaScript進行的一種攻擊。
(2)SQL注入攻擊(3)CSRF(Cross-Site Request Forgeries,跨站點請求偽造):指攻擊者通過設置好的陷阱,強制對已完成的認證用戶進行非預期的個人信息或設定信息等某些狀態更新。前端性能
如何優化圖像、圖像格式的區別?
瀏覽器是如何渲染頁面的?
六、設計模式
對MVC、MVVM的理解
七、正則表達式
寫一個function,清除字元串前後的空格。(兼容所有瀏覽器)
function trim(str) { if (str && typeof str === "string") { return str.replace(/(^s*)|(s*)$/g,""); //去除前後空白符 }}
使用正則表達式驗證郵箱格式
var reg = /^(w)+(.w+)*@(w)+((.w{2,3}){1,3})$/; var email = "example@qq.com"; console.log(reg.test(email)); // true
八、職業規劃
對前端工程師這個職位你是怎麼樣理解的?
a. 前端是最貼近用戶的程序員,前端的能力就是能讓產品從 90分進化到 100 分,甚至更好
b. 參與項目,快速高質量完成實現效果圖,精確到1px;
c. 與團隊成員,UI設計,產品經理的溝通;
d. 做好的頁面結構,頁面重構和用戶體驗;
e. 處理hack,兼容、寫出優美的代碼格式;
f. 針對伺服器的優化、擁抱最新前端技術。
推薦閱讀:
※前端開發負責人修鍊指北
※前端日刊-2017.11.18
※《Oli-Zhao的前端一萬小時》之:離不開的Git和GitHub(2)——Git、GitHub進階(提交代碼+團隊合作)
※前端日刊-2018.02.07
※前端日刊-2018.01.29