前段時間找工做,經歷了好幾個公司的面試,獲得一些信息,和你們分享:javascript
- 大部分公司(創業公司)都趨向於招一個牛逼的前端而不是三四個平庸的前端
- 性能優化、ES6必問
- 招聘要求上清一色的要求有一門後端語言的經驗
- 招聘要求寫的和麪試相關性並非很高
- 招人的要求愈來愈高,不要輕易離職,特別是裸辭
如下是我整理我面試遇到的一些我以爲具備表明性的題目,恰好30題,吐血獻上!css
0.談談對前端安全的理解,有什麼,怎麼防範
前端安全問題主要有XSS、CSRF攻擊
XSS:跨站腳本攻擊
它容許用戶將惡意代碼植入到提供給其餘用戶使用的頁面中,能夠簡單的理解爲一種javascript代碼注入。
XSS的防護措施:html
- 過濾轉義輸入輸出
- 避免使用
eval
、new Function
等執行字符串的方法,除非肯定字符串和用戶輸入無關 - 使用cookie的httpOnly屬性,加上了這個屬性的cookie字段,js是沒法進行讀寫的
- 使用innerHTML、document.write的時候,若是數據是用戶輸入的,那麼須要對象關鍵字符進行過濾與轉義
CRSF:跨站請求僞造
其實就是網站中的一些提交行爲,被黑客利用,在你訪問黑客的網站的時候進行操做,會被操做到其餘網站上
CRSF防護措施:前端
- 檢測http referer是不是同域名
- 避免登陸的session長時間存儲在客戶端中
- 關鍵請求使用驗證碼或者token機制
其餘的一些攻擊方法還有HTTP劫持、界面操做劫持java
1.使用箭頭函數須要注意的地方
當要求動態上下文的時候,你就不能使用箭頭函數,好比:定義方法,用構造器建立對象,處理時間時用 this
獲取目標。node
2.webpack.load的原理
loaders是你用在app源碼上的轉換元件。他們是用node.js運行的,把源文件做爲參數,返回新的資源的函數。jquery
3.ES6 let、const
let
let是更完美的varwebpack
- let聲明的變量擁有塊級做用域,let聲明仍然保留了提高的特性,但不會盲目提高。
- let聲明的全局變量不是全局對象的屬性。不能夠經過
window.變量名
的方式訪問 - 形如
for (let x…)
的循環在每次迭代時都爲x
建立新的綁定 - let聲明的變量直到控制流到達該變量被定義的代碼行時纔會被裝載,因此在到達以前使用該變量會觸發錯誤。
const
定義常量值,不能夠從新賦值,可是若是值是一個對象,能夠改變對象裏的屬性值git
const OBJ = {"a":1, "b":2}; OBJ.a = 3; OBJ = {};// 從新賦值,報錯! console.log(OBJ.a); // 3
4.CSS3 box-sizing的做用
設置CSS盒模型爲標準模型或IE模型。標準模型的寬度只包括content,二IE模型包括border和paddingweb
box-sizing屬性能夠爲三個值之一:
- content-box,默認值,border和padding不計算入width以內
- padding-box,padding計算入width內
- border-box,border和padding計算入width以內
5.說說HTML5中有趣的標籤(新標籤及語義化)
若是代碼寫的語義化,有利於SEO。搜索引擎就會很容易的讀懂該網頁要表達的意思。例如文本模塊要有大標題,合理利用h1-h6,列表形式的代碼使用ul或ol,重要的文字使用strong等等。總之就是要充分利用各類HTML標籤完成他們本職的工做
6.git命令,如何批量刪除分支
git branch |grep 'branchName' |xargs git branch -D
,從分支列表中匹配到指定分支,而後一個一個(分紅小塊)傳遞給刪除分支的命令,最後進行刪除。(參考這裏)
7.建立對象的三種方法
第一種方式,字面量
var o1 = {name: "o1"} var o2 = new Object({name: "o2"})
第二種方式,經過構造函數
var M = function(name){ this.name = name } var o3 = new M("o3")
第三種方式,Object.create
var p = {name: "p"} var o4 = Object.create(p)
新建立的對o4的原型就是p,同時o4也擁有了屬性name
8.JS實現繼承的幾種方式
借用構造函數實現繼承
function Parent1(){ this.name = "parent1" } function Child1(){ Parent1.call(this); this.type = "child1"; }
缺點:Child1沒法繼承Parent1的原型對象,並無真正的實現繼承(部分繼承)
借用原型鏈實現繼承
function Parent2(){ this.name = "parent2"; this.play = [1,2,3]; } function Child2(){ this.type = "child2"; } Child2.prototype = new Parent2();
缺點:原型對象的屬性是共享的
組合式繼承
function Parent3(){ this.name = "parent3"; this.play = [1,2,3]; } function Child3(){ Parent3.call(this); this.type = "child3"; } Child3.prototype = Object.create(Parent3.prototype); Child3.prototype.constructor = Child3;
9.當new Foo()時發生了什麼
1.建立了一個新對象
2.將this指向這個新對象
3.執行構造函數裏面的代碼
4.返回新對象(this)
參考《JS高程》6.6.2
10.你作過哪些性能優化
雪碧圖,移動端響應式圖片,靜態資源CDN,減小Dom操做(事件代理、fragment),壓縮JS和CSS、HTML等,DNS預解析
11.瀏覽器渲染原理
- HTML被解析成DOM Tree,CSS被解析成CSS Rule Tree
- 把DOM Tree和CSS Rule Tree通過整合生成Render Tree(佈局階段)
- 元素按照算出來的規則,把元素放到它該出現的位置,經過顯卡畫到屏幕上
更多詳情看這裏
12.前端路由的原理
什麼是路由?簡單的說,路由是根據不一樣的 url 地址展現不一樣的內容或頁面
使用場景?前端路由更多用在單頁應用上, 也就是SPA, 由於單頁應用, 基本上都是先後端分離的, 後端天然也就不會給前端提供路由。
前端的路由和後端的路由在實現技術上不同,可是原理都是同樣的。在 HTML5 的 history API 出現以前,前端的路由都是經過 hash 來實現的,hash 能兼容低版本的瀏覽器。
兩種實現前端路由的方式
HTML5 History兩個新增的API:history.pushState
和 history.replaceState
,兩個 API 都會操做瀏覽器的歷史記錄,而不會引發頁面的刷新。
Hash就是url 中看到 #
,咱們須要一個根據監聽哈希變化觸發的事件( hashchange
) 事件。咱們用 window.location
處理哈希的改變時不會從新渲染頁面,而是看成新頁面加到歷史記錄中,這樣咱們跳轉頁面就能夠在 hashchange 事件中註冊 ajax 從而改變頁面內容。
優勢
從性能和用戶體驗的層面來比較的話,後端路由每次訪問一個新頁面的時候都要向服務器發送請求,而後服務器再響應請求,這個過程確定會有延遲。而前端路由在訪問一個新頁面的時候僅僅是變換了一下路徑而已,沒有了網絡延遲,對於用戶體驗來講會有至關大的提高。
更多內容請看這裏
缺點
使用瀏覽器的前進,後退鍵的時候會從新發送請求,沒有合理地利用緩存。
13.Restful API是什麼
- Restful的意思就是表現層狀態轉化。
- 「表現層」其實指的是」資源」(Resources)的」表現層」,把」資源」具體呈現出來的形式,叫作它的」表現層」(Representation)。
- 所謂」資源」,就是網絡上的一個實體,或者說是網絡上的一個具體信息。它能夠是一段文本、一張圖片、一首歌曲、一種服務,總之就是一個具體的實在,每個URI表明一種資源。
- 若是客戶端想要操做服務器,必須經過某種手段,讓服務器端發生」狀態轉化」(State Transfer)。而這種轉化是創建在表現層之上的,因此就是」表現層狀態轉化」。
- Restful就是客戶端和服務器之間,傳遞這種資源的某種表現層
- 客戶端經過四個HTTP動詞,對服務器端資源進行操做,實現」表現層狀態轉化」
Restful API就是符合Restful架構的API設計。
Restful API一些具體實踐:
- 應該儘可能將API部署在專用域名之下。若是肯定API很簡單,不會有進一步擴展,能夠考慮放在主域名下。
- 應該將API的版本號放入URL。
- 對於資源的具體操做類型,由HTTP動詞表示
- 若是記錄數量不少,服務器不可能都將它們返回給用戶。API應該提供參數,過濾返回結果
- 若是狀態碼是4xx,就應該向用戶返回出錯信息。通常來講,返回的信息中將error做爲鍵名
…..
14.script標籤的defer、async的區別
defer是在HTML解析完以後纔會執行,若是是多個,按照加載的順序依次執行
async是在加載完成後當即執行,若是是多個,執行順序和加載順序無關
15.同源與跨域
什麼是同源策略?
限制從一個源加載的文檔或腳本如何與來自另外一個源的資源進行交互。
一個源指的是主機名、協議和端口號的組合,必須相同
跨域通訊的幾種方式
- JSONP
- Hash
- postMessage
- WebSocket
- CORS
JSONP原理
基本原理:利用script
標籤的異步加載特性實現
給服務端傳一個回調函數,服務器返回一個傳遞過去的回調函數名稱的JS代碼
更多請查看:《先後端通訊類知識》
16.原型與閉包相關問題
原型是什麼
原型就是一個普通的對象,每一個對象都有一個原型(Object除外),原型能存儲咱們的方法,構造函數建立出來的實例對象可以引用原型中的方法。
查看原型
之前通常使用對象的__proto__
屬性,ES6推出後,推薦用Object.getPrototypeOf()
方法來獲取對象的原型
閉包是什麼?
專業說法:當一個內部函數被其外部函數以外的變量引用時,就造成了一個閉包。
還能夠這麼理解:
閉包就是一個具備封閉功能與包裹功能的結構,是爲了實現具備私有訪問空間的函數的,函數能夠構成閉包,由於函數內部定義的數據函數外部沒法訪問,即函數具備封閉性;函數能夠封裝代碼即具備包裹性,因此函數能夠構成閉包。
建立閉包的最多見的方式就是在一個函數內建立另外一個函數,經過另外一個函數訪問這個函數的局部變量
閉包的特性
閉包有三個特性:
- 函數嵌套函數
- 函數內部能夠引用外部的參數和變量
- 參數和變量不會被垃圾回收機制回收
閉包有什麼用,使用場景
當咱們須要在模塊中定義一些變量,並但願這些變量一直保存在內存中但又不會「污染」全局的變量時,就能夠用閉包來定義這個模塊。
閉包的缺點
閉包的缺點就是常駐內存,會增大內存使用量,使用不當很容易形成內存泄露。
函數套函數就是閉包嗎?不是!,當一個內部函數被其外部函數以外的變量引用時,纔會造成了一個閉包。
更多內容請看這裏
17.如何進行錯誤監控
前端錯誤的分類
- 即時運行錯誤(代碼錯誤)
- 資源加載錯誤
錯誤的捕獲方式
即時運行錯誤的捕獲方式:
- try…catch
- window.onerror
資源加載錯誤:
- object.onerror(如img,script)
- performance.getEntries()
- Error事件捕獲
延伸:跨域的js運行錯誤能夠捕獲嗎,錯誤提示什麼,應該怎麼處理?
能夠。
Script error
1.在script標籤增長crossorigin屬性
2.設置js資源響應頭Access-Control-Allow-Orgin:*
上報錯誤的基本原理
採用Ajax通訊方式上報
利用Image對象上報
18.DOM事件類
DOM事件的級別
- DOM0,element.onclick = function(){}
- DOM2,element.addEventListener(‘click’, function(){}, false);
DOM事件模型是什麼:指的是冒泡和捕獲
DOM事件流是什麼:捕獲階段 -> 目標階段 -> 冒泡階段
描述DOM事件捕獲的具體流程
window –> document –> documentElement(html標籤) –> body –> …. –> 目標對象
Event對象常見應用
- event.preventDefault(),阻止默認行爲
- event.stopPropagation(),阻止事件冒泡
- event.stopImmediatePropagation(),阻止剩餘的事件處理函數執行而且防止事件冒泡到DOM樹上,這個方法不接受任何參數。
- event.currentTarget,返回綁定事件的元素
- event.target,返回觸發事件的元素
如何自定義事件
Event,不能傳遞參數
var eve = new Event('自定義事件名'); ev.addEventListener('自定義事件名', function(){ console.log('自定義事件') }); ev.dispatchEvent(eve);
CustomEvent,還能夠指定參數
19.本地起了一個http server,爲何只能在同一個WIFI(局域網)上訪問?
你沒有公網IP固然就不能被外網訪問了。常見的WIFI狀況下,通常的ip會是~192.168.0.x·這樣的,只是對局域網(同WIFI下)可見,可是外網是訪問不了的。(segmentfault上的答案)
20.迴流和重繪
21.數組去重的方法
22.深拷貝與淺拷貝
是什麼
淺拷貝只複製指向某個對象的指針,而不復制對象自己,新舊對象仍是共享同一塊內存。但深拷貝會另外創造一個如出一轍的對象,新對象跟原對象不共享內存,修改新對象不會改到原對象。
實現淺拷貝
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = obj1; obj2.b = 100; console.log(obj1); // { a: 10, b: 100, c: 30 } <-- b 被改到了 console.log(obj2); // { a: 10, b: 100, c: 30 }
實現深拷貝
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c }; obj2.b = 100; console.log(obj1); // { a: 10, b: 20, c: 30 } <-- b 沒被改到 console.log(obj2); // { a: 10, b: 100, c: 30 }
深拷貝實現方式
- 手動複製方式,如上面的代碼,缺點就是
-
Object.assign,ES6 的新函數,能夠幫助咱們達成跟上面同樣的功能。
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = Object.assign({}, obj1); obj2.b = 100; console.log(obj1); // { a: 10, b: 20, c: 30 } <-- 沒被改到 console.log(obj2); // { a: 10, b: 100, c: 30 }
-
轉成 JSON 再轉回來
用JSON.stringify把對象轉成字符串,再用JSON.parse把字符串轉成新的對象。
缺點:只有能夠轉成JSON格式的對象才能夠這樣用,像function沒辦法轉成JSON。 - jquery,有提供一個$.extend能夠用來作 Deep Copy。
- lodash,也有提供_.cloneDeep用來作 Deep Copy。
- 遞歸實現深拷貝
function clone( o ) { var temp = {}; for( var k in o ) { if( typeof o[ k ] == 'object' ){ temp[ k ] = clone( o[ k ] ); } else { temp[ k ] = o[ k ]; } } return temp; }
參考文章:關於 JS 中的淺拷貝和深拷貝,進擊JavaScript之(四)玩轉遞歸與數列
23.如何快速合併雪碧圖
Gulp:gulp-css-spriter
webpack:optimize-css-assets-webpack-plugin
Go!Png
在線工具
24.代碼優化基本方法
減小HTTP請求
HTML優化:
- 使用語義化標籤
- 減小iframe:iframe是SEO的大忌,iframe有好處也有弊端
- 避免重定向
CSS優化:
- 佈局代碼寫前面
- 刪除空樣式
- 不濫用浮動,字體,須要加載的網絡字體根據網站需求再添加
- 選擇器性能優化
- 避免使用表達式,避免用id寫樣式
js優化:
- 壓縮
- 減小重複代碼
圖片優化:
- 使用WebP
- 圖片合併,CSS sprite技術
減小DOM操做
- 緩存已經訪問過的元素
- 「離線」更新節點, 再將它們添加到樹中
- 避免使用 JavaScript 輸出頁面佈局–應該是 CSS 的事兒
使用JSON格式來進行數據交換
使用CDN加速
使用HTTP緩存:添加 Expires
或 Cache-Control
信息頭
使用DNS預解析
Chrome內置了DNS Prefetching技術, Firefox 3.5 也引入了這一特性,因爲Chrome和Firefox 3.5自己對DNS預解析作了相應優化設置,因此設置DNS預解析的不良影響之一就是可能會下降Google Chrome瀏覽器及火狐Firefox 3.5瀏覽器的用戶體驗。
預解析的實現:
- 用meta信息來告知瀏覽器, 當前頁面要作DNS預解析:
<meta http-equiv="x-dns-prefetch-control" content="on" />
- 在頁面header中使用link標籤來強制對DNS預解析:
<link rel="dns-prefetch" href="http://bdimg.share.baidu.com" />
25.HTTPS的握手過程
- 瀏覽器將本身支持的一套加密規則發送給服務器。
- 服務器從中選出一組加密算法與HASH算法,並將本身的身份信息以證書的形式發回給瀏覽器。證書裏面包含了網站地址,加密公鑰,以及證書的頒發機構等信息。
- 瀏覽器得到網站證書以後瀏覽器要作如下工做:
- 驗證證書的合法
- 若是證書受信任,或者是用戶接受了不受信的證書,瀏覽器會生成一串隨機數的密碼,並用證書中提供的公鑰加密。
- 使用約定好的HASH算法計算握手消息,並使用生成的隨機數對消息進行加密,最後將以前生成的全部信息發送給服務器
- 網站接收瀏覽器發來的數據以後要作如下的操做:
- 使用本身的私鑰將信息解密取出密碼,使用密碼解密瀏覽器發來的握手消息,並驗證HASH是否與瀏覽器發來的一致。
- 使用密碼加密一段握手消息,發送給瀏覽器。
- 瀏覽器解密並計算握手消息的HASH,若是與服務端發來的HASH一致,此時握手過程結束,以後全部的通訊數據將由以前瀏覽器生成的隨機密碼並利用對稱加密算法進行加密。
26.BFC相關問題
BFC(Block formatting context)直譯爲」塊級格式化上下文」。它是一個獨立的渲染區域,只有 Block-level box 參 與, 它規定了內部的 Block-level Box 如何佈局,而且與這個區域外部絕不相干。
BFC的渲染規則
- BFC這個元素的垂直方向的邊距會發生重疊
- BFC的區域不會與浮動元素的box重疊(清除浮動原理)
- BFC在頁面上是一個獨立的容器,外面的元素不會影響它裏面的元素,反過來它裏面的元素也不會影響外面的元素
- 計算BFC的高度的時候,浮動元素也會參與計算
如何建立BFC?
- overflow屬性不爲visible
- float屬性不爲none
- position屬性爲absolute或fixed
- display屬性爲inline-block、table-cell、table-caption、flex、inline-flex
BFC的使用場景
他的很經常使用的一個應用場景就是解決邊距重疊的問題.
27.響應式圖片
1.JS或者服務端硬編碼,resize事件,判斷屏幕大小加載不一樣的圖片
2.img srcset 方法
3.picture標籤 -> source
4.svg
5.第三方庫polyfill
28.判斷一個變量是不是數組
var a = []; // 1.基於instanceof a instanceof Array; // 2.基於constructor a.constructor === Array; // 3.基於Object.prototype.isPrototypeOf Array.prototype.isPrototypeOf(a); // 4.基於getPrototypeOf Object.getPrototypeOf(a) === Array.prototype; // 5.基於Object.prototype.toString Object.prototype.toString.apply(a) === '[object Array]'; // 6.Array.isArray Array.isArray([]); // true
以上,除了Object.prototype.toString
外,其它方法都不能正確判斷變量的類型。
29.UTF-8和Unicode的區別
UTF-8就是在互聯網上使用最廣的一種unicode的實現方式。Unicode的出現是爲了統一地區性文字編碼方案,爲解決unicode如何在網絡上傳輸的問題,因而面向傳輸的衆多 UTF(UCS Transfer Format)標準出現了,顧名思義,UTF-8就是每次8個位傳輸數據,而UTF-16就是每次16個位。ASCII –> 地區性編碼(GBK) –> Unicode –> UTF-8