前端面試概念收集器

前端面試特輯包含前端面試概念收集器,前端面試的經典題,前端面試的難題和怪題 - 知乎專欄。

該文章分為 概念,原生Javascript,css知識點,http協議,網路安全,性能優化。

概念

Commonjs 在Nodejs服務端上運行,無法在瀏覽器端運行。為了滿足瀏覽器端模塊化的要求,才有了AMD和CMD。

AMD (Asynchronous Module Definition)是 RequireJS 在推廣過程中對模塊定義的規範化產出。對於依賴的模塊,AMD 是提前執行。AMD 推崇依賴前置,把依賴參數以數組形式保存在前半部分。使用規則如下:

define(id?, dependencies?, factory);n

CMD (Common Module Definition)是 Seajs 在推廣過程中對模塊定義的規範化產出。 CMD 是延遲執行,CMD 推崇依賴就近,使用規則如下:

define(function(require, exports, module) {n // 模塊代碼n});n

Require.js 和Sea.js都是模塊載入器,兩者的主要區別如下:

  • 定位有差異。RequireJS 想成為瀏覽器端的模塊載入器,同時也想成為 Rhino / Node 等環境的模塊載入器。Sea.js 則專註於 Web 瀏覽器端,同時通過 Node 擴展的方式可以很方便跑在 Node 環境中。
  • 遵循的規範不同。RequireJS 遵循 AMD(非同步模塊定義)規範,Sea.js 遵循 CMD (通用模塊定義)規範。規範的不同,導致了兩者 API 不同。Sea.js 更貼近 CommonJS Modules/1.1 和 Node Modules 規範。
  • 推廣理念有差異。RequireJS 在嘗試讓第三方類庫修改自身來支持 RequireJS,目前只有少數社區採納。Sea.js 不強推,採用自主封裝的方式來「海納百川」,目前已有較成熟的封裝策略。
  • 對開發調試的支持有差異。Sea.js 非常關注代碼的開發調試,有 nocache、debug 等用於調試的插件。RequireJS 無這方面的明顯支持。
  • 插件機制不同。RequireJS 採取的是在源碼中預留介面的形式,插件類型比較單一。Sea.js 採取的是通用事件機制,插件類型更豐富。

    來自CMD 模塊定義規範

UMD (Universal Module Definition),AMD,CommonJS規範是兩種不一致的規範,雖然他們應用的場景也不太一致,但是人們仍然是期望有一種統一的規範來支持這兩種規範,對兩種情況進行判斷,兼容兩個規範。

(function (root, factory) {n if (typeof define === function && define.amd) {n // AMDn define([jquery], factory);n } else if (typeof exports === object) {n // Node, CommonJS-liken module.exports = factory(require(jquery));n } else {n // Browser globals (root is window)n root.returnExports = factory(root.jQuery);n }n}(this, function ($) {n // methodsn function myFunc(){};nn // exposed public methodn return myFunc;n}));n

原生Javascript

在做項目或者產品的過程當中,可能你對框架和庫的使用非常多,往往忽視了基礎知識。當然,大公司不僅僅希望你是一個api調用工程師,所以對基礎知識的考察越來越重要。隨著瀏覽器的兼容性越來越好,原生js的重要性也日益明顯。

原生函數

Array

  • every() 檢測數組所有元素是否都符合指定條件,只要有一個不滿足則false。
  • some() 檢測數組元素中是否有元素符合指定條件,只要有一個滿足則true
  • concat() 連接兩個或更多的數組,並返回結果。
  • join() 把數組的所有元素放入一個字元串。元素通過指定的分隔符進行分隔。
  • pop() 刪除並返回數組的最後一個元素
  • push() 向數組的末尾添加一個或更多元素,並返回新的長度。
  • reverse() 顛倒數組中元素的順序。
  • shift() 刪除並返回數組的第一個元素
  • slice() 從某個已有的數組返回選定的元素
  • sort() 對數組的元素進行排序
  • splice() 刪除元素,並向數組添加新元素。

Math

  • abs(x) 返回數的絕對值。
  • acos(x) 返回數的反餘弦值。
  • asin(x) 返回數的反正弦值。
  • atan(x) 以介於 -PI/2 與 PI/2 弧度之間的數值來返回 x 的反正切值。
  • atan2(y,x) 返回從 x 軸到點 (x,y) 的角度(介於 -PI/2 與 PI/2 弧度之間)。
  • ceil(x) 對數進行上舍入。
  • cos(x) 返回數的餘弦。
  • exp(x) 返回 e 的指數。
  • floor(x) 對數進行下舍入。
  • log(x) 返回數的自然對數(底為e)。
  • max(x,y) 返回 x 和 y 中的最高值。
  • min(x,y) 返回 x 和 y 中的最低值。
  • pow(x,y) 返回 x 的 y 次冪。
  • random()返回 0 ~ 1 之間的隨機數。
  • round(x) 把數四捨五入為最接近的整數。
  • sin(x) 返回數的正弦。
  • sqrt(x) 返回數的平方根。
  • tan(x) 返回角的正切。

String

  • anchor() 創建 HTML 錨。
  • big()用大號字體顯示字元串。
  • blink() 顯示閃動字元串。
  • bold() 使用粗體顯示字元串。
  • charAt() 返回在指定位置的字元。
  • charCodeAt() 返回在指定的位置的字元的 Unicode 編碼。
  • concat() 連接字元串。
  • fixed() 以打字機文本顯示字元串。
  • fontcolor() 使用指定的顏色來顯示字元串。
  • fontsize() 使用指定的尺寸來顯示字元串。
  • fromCharCode()從字元編碼創建一個字元串。
  • indexOf() 檢索字元串。
  • italics() 使用斜體顯示字元串。
  • lastIndexOf() 從後向前搜索字元串。
  • link() 將字元串顯示為鏈接。
  • localeCompare() 用本地特定的順序來比較兩個字元串。
  • match()找到一個或多個正則表達式的匹配。
  • replace() 替換與正則表達式匹配的子串。
  • search() 檢索與正則表達式相匹配的值。
  • slice()提取字元串的片斷,並在新的字元串中返回被提取的部分。
  • small() 使用小字型大小來顯示字元串。
  • split() 把字元串分割為字元串數組。
  • strike() 使用刪除線來顯示字元串。
  • sub() 把字元串顯示為下標。
  • substr() 從起始索引號提取字元串中指定數目的字元。
  • substring() 提取字元串中兩個指定的索引號之間的字元。
  • sup() 把字元串顯示為上標。

原生Javascript求數組最小值和最大值

Math.min.apply(null, array)nMath.max.apply(null, array)n

原生Dom操作

  • 刪除 removeChild 只刪除下一級
  • 移動 appendChild 捕獲一個dom插入
  • 複製 cloneNode true 深克隆 false 淺克隆
  • 插入 appendChild 新建一個dom插入
  • 替換 replaceChild
  • 前插後插 insertBefore 後插需要用nextSibling找到下一個節點

查找

  • getElementsByTagName() 通過標籤名稱
  • getElementsByName() 通過元素的Name屬性的值
  • getElementById() 通過元素Id,唯一性

重繪重排

當DOM的變化影響了元素的幾何屬性(寬或高),瀏覽器需要重新計算元素的幾何屬性,同樣其他元素的幾何屬性和位置也會因此受到影響。瀏覽器會使渲染樹中受到影響的部分失效,並重新構造渲染樹。這個過程稱為重排。完成重排後,瀏覽器會重新繪製受影響的部分到屏幕,該過程稱為重繪,參考高性能JavaScript DOM編程以及重排與重繪。

事件流(捕獲冒泡),參考JavaScript的事件機制

從document開始,到document結束。事件流分為三個階段:

  1. 事件捕獲階段
  2. 處於目標階段
  3. 事件冒泡階段

事件流分為兩類:捕獲型事件和冒泡型事件。

  • 捕獲型事件

從根元素向下傳播,從body開始往每一個div。方法是addEventListener。(true:捕獲,false:冒泡,默認:false)

  • 冒泡型事件

由當前dom向上傳播,從div到body。方法是onclick事件。

委派代理 參考JavaScript事件代理和委託(Delegation)

var delegate = function(client, clientMethod) {n return function() {n return clientMethod.apply(client, arguments);n }n }n var ClassA = function() {n var _color = "red";n return {n getColor: function() {n console.log("Color: " + _color);n },n setColor: function(color) {n _color = color;n }n };n };nn var a = new ClassA();n a.getColor();n a.setColor("green");n a.getColor();n console.log("執行代理!");n var d = delegate(a, a.setColor);n d("blue");n console.log("執行完畢!");n a.getColor();n

兼容性寫法

ie下的兼容性問題,js舉例,(轉載)IE8+兼容經驗小結。

IE6能識別下劃線"_"和星號" * ",IE7能識別星號" * ",但不能識別下劃線"_",IE6~IE10都認識"9",但firefox前述三個都不能認識。

<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">n

動畫方面,加速度,重力模擬實現

正則,基本用法和相關函數作用 參考深入淺出的javascript的正則表達式學習教程。

必須要死記硬背的事d數字,即「digit」,w字母,即「word」,s空格或tab,即「space」。{3}是指有3個這樣的字元。+指是一個或多個。*是任意個也可以沒有。

new RegExp(pattern,attributes);n

其中,參數pattern是一個字元串,指定了正則表達式的模式;參數attributes是一個可選的參數,包含屬性 g,i,m,分別使用與全局匹配,不區分大小寫匹配,多行匹配。

OOP

如果你需要補救Javascript面向對象這一方面,先看廖雪峰老師的Javascript原型繼承,以及廖雪峰老師的Javascript面向對象編程(二):構造函數的繼承。你必須掌握好一個概念就是原型鏈 。

類繼承方法

類的繼承有4種方法。比較完美的方法是聲明一個空對象,作為中間prototype,參考brandonxiang/example-mocha/demo5。

私有變數

GlobalScope和LocalScope是指面向對象中的共有或私有變數函數,全局變數的搜索較慢,減少document的訪問。私有變數和公有變數是Javascript基礎開發的一個重要環節。下面是一個簡單的例子,name是公用變數,它是this的一個屬性。age是一個私有變數,但是它能被對應的公有方法調用。

function Person(props){n this.name =brandon;n var age = 26;nn this.setAge = function(_age){n age = _age;n }n this.getAge = function(){n return age;n }n}n

變數提升和函數提示和作用域

一道容易做錯的JavaScript面試題很好地講述了這個問題。

如果你還是不懂。我舉幾個簡單的例子,來自你不知道的Javascript。

變數提升

a=2;nvar a;nconsole.log(a);n

結果輸出為2。由於var a;變數提升,提升到代碼的頂端,而它不會改變數值。代碼怎變成了:

var a;na=2;nconsole.log(a);n

如果題目情況是下面這樣。

console.log(a);nvar a = 2;n

結果輸出是undefined。只有var a;才會提升。a=2;並不會提升。

函數提升

foo(); //3nnfunction foo(){n console.log(1);n}nnvar foo = function(){n console.log(2);n}nnfoo(); //2nnfunction foo(){n console.log(3);n}n

定義為function會直接引起函數提升,提升到文件最上端,第一次foo()輸出2。而且後一個會將前一個覆蓋。var foo = function(){}不會被提升。在後面的函數調用會覆蓋,第二次foo()輸出2。

作用域

  • 若apply或者call直接作用於對象,this屬性必須是該對象
  • 方法被提取或者出現(a=a)()或(a,a)()這樣奇葩的調用一般都是上級或者window
  • 沒有var的情況,請找上級對象
  • 箭頭函數需特別注意

閉包

內存泄漏的原因和場景

  • 頻繁操作iframe
  • 動態創建DOM
  • 事件綁定
  • Ext框架本身

h5里一些新增api的了解H5的新特性及部分API詳解

cookie,localstorage和sessionstorage

cookie與localstorage區別

  • cookie的大小是受限的
  • 請求一個新的頁面的時候cookie都會被發送過去
  • cookie指定作用域,不可以跨域調用
  • cookie是http規範的一部分,localstorage在本地「存儲」數據
  • localstorage是html5的新特性,所以舊瀏覽器不一定兼容

localstorage與sessionstorage區別

存儲在 localStorage 裡面的數據沒有過期時間(expiration time),而存儲在 sessionStorage 裡面的數據會在瀏覽器會話(browsing session)結束時被清除,即瀏覽器關閉時。

瀏覽器的對象模型

  • window
  • document
  • history
  • location
  • screen

CSS知識點

塊元素

div center h1 hr table ul ol

內聯元素

span a font img strong sub

模型盒

offsetwidth = width + border + padding

clientwidth = width + padding

doctype

html 5 的doctype寫法 <!DOCTYPE html>

  • 正確使用DOCTYPE
  • CS002: DOCTYPE 與瀏覽器模式分析

haslayout

hack寫法參考 史上最全的CSS hack方式一覽

link和@import的區別

  • link是XHTML標籤,除了載入CSS外,還可以定義RSS等其他事務;@import屬於CSS範疇,只能載入CSS。

  • link引用CSS時,在頁面載入時同時載入;@import需要頁面網頁完全載入以後載入。

  • link是XHTML標籤,無兼容問題;@import是在CSS2.1提出的,低版本的瀏覽器不支持。

  • link支持使用Javascript控制DOM去改變樣式;而@import不支持。

網路安全

XSS

XSS(Cross Site Scripting),是一種注入攻擊。沒有過濾掉<script>以及其他敏感關鍵詞的忽視。主要是針對對方的cookie和用戶緩存信息進行攻擊。

CRSF

原理

CSRF(Cross-site request forgery)跨域請求偽造,又叫one click attack或session riding。

它們之間的區別在於:XSS利用站點內的信任用戶。而CSRF是通過偽裝來自受信任用戶的請求來利用受信任的網站。這種方式雖然不是很流行,但是卻難以防範,其危害也不比其他安全漏洞小。

下面是CSRF的常見特性:

  • 依靠用戶標識危害網站
  • 利用網站對用戶標識的信任
  • 欺騙用戶的瀏覽器發送HTTP請求給目標站點
  • 另外可以通過IMG標籤會觸發一個GET請求,可以利用它來實現CSRF攻擊。

防範措施

  • 服務端進行CSRF防禦,在表單當中增加偽隨機數。
  • 驗證碼
  • One-Time Tokens
  • 持久化的授權方法切換成瞬間的授權方法。
  • 雙提交cookie

http協議

報文格式

報文格式分為請求報文和響應報文。

請求報文

請求報文又分為4個部分。

  • request-line 請求方法get,post,head,put,delete等
  • headers 請求頭部由關鍵字/值對組成,每行一對,關鍵字和值用英文冒號「:」分隔
  • blank line 最後一個請求頭之後是一個空行,發送回車符和換行符,通知伺服器以下不再有請求頭。
  • request-body 請求數據不在GET方法中使用,而是在POST方法中使用。與請求數據相關的最常使用的請求頭是Content-Type和Content-Length。

響應報文

響應報文報文又分為4個部分。

  • <status-line>狀態行
    • 1xx:指示信息--表示請求已接收,繼續處理。
    • 2xx:成功--表示請求已被成功接收、理解、接受。
    • 3xx:重定向--要完成請求必須進行更進一步的操作。
    • 4xx:客戶端錯誤--請求有語法錯誤或請求無法實現。
    • 5xx:伺服器端錯誤--伺服器未能實現合法的請求。
    • 200 OK:客戶端請求成功。
    • 400 Bad Request:客戶端請求有語法錯誤,不能被伺服器所理解。
    • 401 Unauthorized:請求未經授權,這個狀態代碼必須和WWW-Authenticate報頭域一起使用。
    • 403 Forbidden:伺服器收到請求,但是拒絕提供服務。
    • 404 Not Found:請求資源不存在,舉個例子:輸入了錯誤的URL。
    • 500 Internal Server Error:伺服器發生不可預期的錯誤。
    • 503 Server Unavailable:伺服器當前不能處理客戶端的請求,一段時間後可能恢復正常,舉個例子:HTTP/1.1 200 OK(CRLF)。
  • <headers>消息報頭
  • <blank line>
  • [<response-body>] 響應正文

get與post區別

get

要求伺服器請求URL定位的資源放在響應報文的數據部分,回送客戶端。請求參數和對應的值之間跟在URL後面。利用一個問號(?)代表著url的結束和請求參數的開始。傳遞參數長度受到限制。長度限制1024個字元。

缺點

  • 不適合傳送私密數據
  • 數據量大不適合使用get方式

post

請求行中不包含數據字元串,這些數據保存在請求內容中,各數據之間用&分割開。post也能完成get請求。

關於HTTP請求GET和POST的區別

1.GET提交,請求的數據會附在URL之後(就是把數據放置在HTTP協議頭<request-line>中),以?分割URL和傳輸數據,多個參數用&連接;例如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0 %E5%A5%BD。如果數據是英文字母/數字,原樣發送,如果是空格,轉換為+,如果是中文/其他字元,則直接把字元串用BASE64加密,得出如: %E4%BD%A0%E5%A5%BD,其中%XX中的XX為該符號以16進位表示的ASCII。

POST提交:把提交的數據放置在是HTTP包的包體<request-body>中。上文示例中紅色字體標明的就是實際的傳輸數據

因此,GET提交的數據會在地址欄中顯示出來,而POST提交,地址欄不會改變

2.傳輸數據的大小:

首先聲明,HTTP協議沒有對傳輸的數據大小進行限制,HTTP協議規範也沒有對URL長度進行限制。 而在實際開發中存在的限制主要有:

GET:特定瀏覽器和伺服器對URL長度有限制,例如IE對URL長度的限制是2083位元組(2K+35)。對於其他瀏覽器,如Netscape、FireFox等,理論上沒有長度限制,其限制取決於操作系統的支持。

因此對於GET提交時,傳輸數據就會受到URL長度的限制。

POST:由於不是通過URL傳值,理論上數據不受限。但實際各個WEB伺服器會規定對post提交數據大小進行限制,Apache、IIS6都有各自的配置。

3.安全性:

POST的安全性要比GET的安全性高。注意:這裡所說的安全性和上面GET提到的「安全」不是同個概念。上面「安全」的含義僅僅是不作數據修改,而這裡安全的含義是真正的Security的含義,比如:通過GET提交數據,用戶名和密碼將明文出現在URL上,因為(1)登錄頁面有可能被瀏覽器緩存, (2)其他人查看瀏覽器的歷史紀錄,那麼別人就可以拿到你的賬號和密碼了。

優化性能

結合移動開發規範概述,我的總結:

  • 圖片使用CSS Sprites 或 DataURI
  • 壓縮靜態資源(HTML/CSS/JS/Image)
  • 外鏈 CSS 中避免 @import 引入
  • 初始請求資源數 < 4
  • 數據離線化,考慮將數據緩存在 localStorage
  • 考慮內嵌小型的靜態資源內容
  • 初始請求資源gzip後總體積<50kb
  • 避免打包大型類庫
  • 確保接入層已開啟Gzip壓縮(考慮提升Gzip級別,使用CPU開銷換取載入時間)
  • 盡量使用CSS3代替圖片

spa優化

  • 初始首屏之外的靜態資源(JS/CSS)延遲載入
  • 初始首屏之外的圖片資源按需載入(判斷可視區域)
  • 單頁面應用(SPA)考慮延遲載入非首屏業務模塊
  • 開啟Keep-Alive鏈路復用

運行性能優化, 達到操作足夠流暢

  • 避免 iOS 300+ms 點擊延時問題
  • 緩存 DOM 選擇與計算
  • 避免觸發頁面重繪的操作
  • Debounce連續觸發的事件(scroll / resize / touchmove等),避免高頻繁觸發執行
  • 儘可能使用事件代理,避免批量綁定事件
  • 使用CSS3動畫代替JS動畫
  • 避免在低端機上使用大量CSS3漸變陰影效果,可考慮降級效果來提升流暢度
  • HTML結構層級保持足夠簡單
  • 盡能少的使用CSS高級選擇器與通配選擇器

參考

  • Vue2.0 中,「漸進式框架」和「自底向上增量開發的設計」這兩個概念是什麼?
  • JavaScript document對象詳解
  • 大部分人都會做錯的經典JS閉包面試題

Javascript面試題

  • javaScript面試題大全
  • 關於Js那些經常出的面試題
  • 深入理解JavaScript的閉包特性 如何給循環中的對象添加事件

前端的知識更新太快,此文持續更新

感想

我面試大大小小很多公司,有這麼一點感想。面試其實是一個雙向的過程,面試官在面試我,檢驗著我的能力。但是,同時,也是我在面試著面試官。面試官的問題是否專業,是否基礎,直接反映出公司對應部門對員工的要求。有些面試官不太懂為啥我會默默的觀察著整個辦公室的一種工作氛圍,有時工作氛圍說明很多問題。其中包括工作人員的態度,流動性,實習生的比例。這些種種因素都會影響你的就業選擇,也希望各位讀者能夠認真擇業,不只是為了一份工資。

各位GIS開發工程師可能也會考慮往前端全棧的方向發展,可以參考一位同行的博客----前端面試筆記。

轉載,請表明出處。總目錄前端經驗收集器

歡迎關注我的微信公眾號:brandonxiang


推薦閱讀:

為什麼總說要注重前端基礎?
教你規範 CSS 的命名和書寫
前端工程師如何規劃自己的職業道路?

TAG:前端工程师 | 前端开发入门 | 前端开发 |