深圳地區近期面試100多道題彙總(含超詳細答案)
前言
你盼世界,我盼望你無bug
。Hello 大家好!我是霖呆呆!
哈哈????,這是一篇面試總結文章,抱歉,webpack
和HTTP
系列的先暫緩一下更新哈,Sorry~
這篇文章是呆呆自己近期的一些面試彙總,算了一下有128道,基本都寫了比較完善的答案,就算沒有寫也有推薦一些好的文章連結,文章篇幅較大,整理總結也花費了很多的時間和心血,題目也是根據公司規模的大小從易到難,算是見證了呆呆面試過程中的不足與成長吧 ????。還希望能幫助到正在一起努力求生存的小夥伴們。
"風浪沒平息 我宣告奔跑的意義"
"這不是叛逆 我只是淋了一場雨"
所有文章內容都已整理至 https://github.com/LinDaiDai/niubility-coding-js 快來給我Star呀????~
(因為近期面的主要都是一些深圳的中小公司,他們也還在招聘中,所以不便透露公司名稱,還請大家理解...)
深圳某做海外加速器公司
4月22日上午
1. DIV+CSS佈局的好處
程式碼精簡,且結構與樣式分離,易於維護
程式碼量減少了,減少了大量的頻寬,頁面載入的也更快,提升了使用者的體驗
對SEO搜尋引擎更加友好,且H5又新增了許多語義化標籤更是如此
允許更多炫酷的頁面效果,豐富了頁面
符合W3C標準,保證網站不會因為網路應用的升級而被淘汰
缺點: 不同瀏覽器對web標準預設值不同,所以更容易出現對瀏覽器的相容性問題。
2. 如何解決a標點選後hover事件失效的問題?
改變a標籤css屬性的排列順序
只需要記住LoVe HAte
原則就可以了:
link→visited→hover→active
比如下面錯誤的程式碼順序:
a:hover{
color: green;
text-decoration: none;
}
a:visited{ /* visited在hover後面,這樣的話hover事件就失效了 */
color: red;
text-decoration: none;
}
正確的做法是將兩個事件的位置調整一下。
注意⚠️各個階段的含義:
a:link
:未訪問時的樣式,一般省略成aa:visited
:已經訪問後的樣式a:hover
:滑鼠移上去時的樣式a:active
:滑鼠按下時的樣式
3. 點選一個input依次觸發的事件
const text = document.getElementById('text');
text.onclick = function (e) {
console.log('onclick')
}
text.onfocus = function (e) {
console.log('onfocus')
}
text.onmousedown = function (e) {
console.log('onmousedown')
}
text.onmouseenter = function (e) {
console.log('onmouseenter')
}
答案:
'onmouseenter'
'onmousedown'
'onfocus'
'onclick'
4. 響應式的好處
對某些資料的修改就能自動更新檢視,讓開發者不用再去操作DOM,有更多的時間去思考業務邏輯。
5. Vue的優點及缺點
首先Vue最核心的兩個特點,「響應式」和「元件化」。
「響應式」:這也就是vue.js最大的優點,通過MVVM思想實現資料的雙向繫結,通過虛擬DOM讓我們可以用資料來操作DOM,而不必去操作真實的DOM,提升了效能。且讓開發者有更多的時間去思考業務邏輯。
「元件化」:把一個單頁應用中的各個模組拆分到一個個元件當中,或者把一些公共的部分抽離出來做成一個可複用的元件。所以元件化帶來的好處就是,提高了開發效率,方便重複使用,使專案的可維護性更強。
「虛擬DOM」,當然,這個不是vue中獨有的。
「缺點」:基於物件配置檔案的寫法,也就是options寫法,開發時不利於對一個屬性的查詢。另外一些缺點,在小專案中感覺不太出什麼,vuex的魔法字串,對ts的支援。相容性上存在一些問題。
6. Vue中hash模式和history模式的區別
最明顯的是在顯示上,
hash
模式的URL
中會夾雜著#
號,而history
沒有。Vue
底層對它們的實現方式不同。hash
模式是依靠onhashchange
事件(監聽location.hash
的改變),而history
模式是主要是依靠的HTML5 history
中新增的兩個方法,pushState()
可以改變url
地址且不會傳送請求,replaceState()
可以讀取歷史記錄棧,還可以對瀏覽器記錄進行修改。當真正需要通過
URL
向後端傳送HTTP
請求的時候,比如常見的使用者手動輸入URL
後回車,或者是重新整理(重啟)瀏覽器,這時候history
模式需要後端的支援。因為history
模式下,前端的URL
必須和實際向後端傳送請求的URL
一致,例如有一個URL
是帶有路徑path
的(例如www.lindaidai.wang/blogs/id
),如果後端沒有對這個路徑做處理的話,就會返回404
錯誤。所以需要後端增加一個覆蓋所有情況的候選資源,一般會配合前端給出的一個404
頁面。
hash:
window.onhashchange = function(event){
// location.hash獲取到的是包括#號的,如"#heading-3"
// 所以可以擷取一下
let hash = location.hash.slice(1);
}
7. react的實現原理?有什麼優缺點?
(技術棧是Vue
,沒用過react
)
8. react的控制元件和非控制元件
同上
深圳某電商公司
4月22日下午
1. null和undefined的區別
null
表示一個"無"
的物件,也就是該處不應該有值;而undefined
表示「未定義」。在轉換為數字時結果不同,
Number(null)
為0
,而undefined
為NaN
。
使用場景上:
null
:
作為函式的引數,表示該函式的引數不是物件
作為物件原型鏈的終點
undefined
:
變數被宣告瞭,但沒有賦值時,就等於undefined
呼叫函式時,應該提供的引數沒有提供,該引數等於undefined
物件沒有賦值屬性,該屬性的值為undefined
函式沒有返回值時,預設返回undefined
2. 氣泡排序演算法和陣列去重
「氣泡排序」:
function bubbleSort (arr) {
for (let i = 0; i < arr.length; i++) {
let flag = true;
for (let j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
flag = false;
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
if (flag) break;
}
}
這個是優化過後的氣泡排序。用了一個flag
來優化,它的意思是:如果「某一次」迴圈中沒有交換過元素,那麼意味著排序已經完成了。
氣泡排序總會執行(N-1)+(N-2)+(N-3)+..+2+1趟,但如果執行到當中某一趟時排序已經完成,或者輸入的是一個有序陣列,那麼後邊的比較就都是多餘的,為了避免這種情況,我們增加一個flag,判斷排序是否在中途就已經完成(也就是判斷有無發生元素交換)
「陣列去重」:
Array.form(new Set(arr))
[...new Set(arr)]
for
迴圈巢狀,利用splice
去重新建陣列,利用
indexOf
或者includes
去重先用
sort
排序,然後用一個指標從第0
位開始,配合while
迴圈去重
當然還有很多,例如用filter、reduce、Map、Object
等,具體可以看:
JavaScript陣列去重(12種方法):https://segmentfault.com/a/1190000016418021
「Array.form(new Set(arr))
或[...new Set(arr)]
」
var arr = [1,1,2,5,6,3,5,5,6,8,9,8];
console.log(Array.from(new Set(arr)))
// console.log([...new Set(arr)])
「for
迴圈巢狀,利用splice
去重」:
function unique (origin) {
let arr = [].concat(origin);
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] == arr[j]) {
arr.splice(j, 1);
j--;
}
}
}
return arr;
}
var arr = [1,1,2,5,6,3,5,5,6,8,9,8];
console.log(unique(arr))
「新建陣列,利用indexOf
去重」:
function unique (arr) {
let res = []
for (let i = 0; i < arr.length; i++) {
if (!res.includes(arr[i])) {
res.push(arr[i])
}
}
return res;
}
var arr = [1,1,2,5,6,3,5,5,6,8,9,8];
console.log(unique(arr))
「先用sort
排序,然後用一個指標從第0
位開始,配合while
迴圈去重」:
function unique (arr) {
arr = arr.sort(); // 排序之後的陣列
let pointer = 0;
while (arr[pointer]) {
if (arr[pointer] != arr[pointer + 1]) { // 若這一項和下一項不相等則指標往下移
pointer++;
} else { // 否則刪除下一項
arr.splice(pointer + 1, 1);
}
}
return arr;
}
var arr = [1,1,2,5,6,3,5,5,6,8,9,8];
console.log(unique(arr))
深圳某雲產品公司
4月23日上午
(從這家公司開始面試稍微有些難度了,面試官小哥哥人也很好,剛開始是一個高冷男神,但是在呆呆的猛烈回答下終於還是對我露出了微笑????,還說他也是掘友,有看過我的文章...掘友真是無處不在啊,感動????)
1. 描述一下Promise
這道題我會先大概介紹一下Promise
:
Promise
是一個物件,它代表了一個非同步操作的最終完成或者失敗。由於它的then
方法和catch、finally
方法會返回一個新的Promise
所以可以允許我們鏈式呼叫,解決了傳統的回撥地獄問題。
再說一下then
以及catch
方法:
(此處我是直接拿我之前的一篇文章《45道Promise題》那裡的總結)
Promise
的狀態一經改變就不能再改變。(見3.1).then
和.catch
都會返回一個新的Promise
。(上面的????1.4證明了)catch
不管被連線到哪裡,都能捕獲上層未捕捉過的錯誤。(見3.2)在
Promise
中,返回任意一個非promise
的值都會被包裹成promise
物件,例如return 2
會被包裝為return Promise.resolve(2)
。Promise
的.then
或者.catch
可以被呼叫多次, 但如果Promise
內部的狀態一經改變,並且有了一個值,那麼後續每次呼叫.then
或者.catch
的時候都會直接拿到該值。(見3.5).then
或者.catch
中return
一個error
物件並不會丟擲錯誤,所以不會被後續的.catch
捕獲。(見3.6).then
或.catch
返回的值不能是 promise 本身,否則會造成死迴圈。(見3.7).then
或者.catch
的引數期望是函式,傳入非函式則會發生值透傳。(見3.8).then
方法是能接收兩個引數的,第一個是處理成功的函式,第二個是處理失敗的函式,再某些時候你可以認為catch
是.then
第二個引數的簡便寫法。(見3.9).finally
方法也是返回一個Promise
,他在Promise
結束的時候,無論結果為resolved
還是rejected
,都會執行裡面的回撥函式。
另外也可以說一下finally
方法:
.finally()
方法不管Promise
物件最後的狀態如何都會執行.finally()
方法的回撥函式不接受任何的引數,也就是說你在.finally()
函式中是沒法知道Promise
最終的狀態是resolved
還是rejected
的它最終返回的預設會是一個「上一次的Promise物件值」,不過如果丟擲的是一個異常則返回異常的
Promise
物件。
最後可以說一下all
以及race
方法:
Promise.all()
的作用是接收一組非同步任務,然後並行執行非同步任務,並且在所有非同步操作執行完後才執行回撥。.race()
的作用也是接收一組非同步任務,然後並行執行非同步任務,只保留取第一個執行完成的非同步操作的結果,其他的方法仍在執行,不過執行結果會被拋棄。Promise.all().then()
結果中陣列的順序和Promise.all()
接收到的陣列順序一致。all和race
傳入的陣列中如果有會丟擲異常的非同步任務,那麼只有最先丟擲的錯誤會被捕獲,並且是被then
的第二個引數或者後面的catch
捕獲;但並不會影響陣列中其它的非同步任務的執行。
2. Promise.all中如果有一個丟擲異常了會如何處理
這個,在上一題已經說到了:
all和race
傳入的陣列中如果有會丟擲異常的非同步任務,那麼只有最先丟擲的錯誤會被捕獲,並且是被then
的第二個引數或者後面的catch
捕獲;但並不會影響陣列中其它的非同步任務的執行。
3. Promise為什麼能鏈式呼叫
由於它的then
方法和catch、finally
方法會返回一個新的Promise
所以可以允許我們鏈式呼叫
4. 描述一下EventLoop的執行過程
一開始整個指令碼作為一個巨集任務執行
執行過程中同步程式碼直接執行,巨集任務進入巨集任務佇列,微任務進入微任務佇列
當前巨集任務執行完出隊,檢查微任務列表,有則依次執行,直到全部執行完
執行瀏覽器UI執行緒的渲染工作
檢查是否有
Web Worker
任務,有則執行執行完本輪的巨集任務,回到2,依此迴圈,直到巨集任務和微任務佇列都為空
(具體可以看這裡:https://juejin.im/post/5e58c618e51d4526ed66b5cf#heading-1)
5. docoment,window,html,body的層級關係
「層級關係」:
window > document > html > body
window
是BOM
的核心物件,它一方面用來獲取或設定瀏覽器的屬性和行為,另一方面作為一個全域性物件。document
物件是一個跟文件相關的物件,擁有一些操作文件內容的功能。但是地位沒有window
高。html
元素物件和document
元素物件是屬於html
文件的DOM
物件,可以認為就是html
原始碼中那些標籤所化成的物件。他們跟div、select
什麼物件沒有根本區別。
(我是這樣記的,整個瀏覽器中最大的肯定就是視窗window
了,那麼進來的我不管你是啥,就算你是document
也得給我盤著)
6. addEventListener函式的第三個引數
第三個引數涉及到冒泡和捕獲,是true
時為捕獲,是false
則為冒泡
7. 有寫過原生的自定義事件嗎
使用
Event
使用
customEvent
(可以傳引數)使用
document.createEvent('CustomEvent')和initCustomEvent()
「建立自定義事件」
原生自定義事件有三種寫法:
使用
Event
let myEvent = new Event('event_name');
使用
customEvent
(可以傳引數)
let myEvent = new CustomEvent('event_name', {
detail: {
// 將需要傳遞的引數放到這裡
// 可以在監聽的回撥函式中獲取到:event.detail
}
})
使用
document.createEvent('CustomEvent')和initCustomEvent()
let myEvent = document.createEvent('CustomEvent');// 注意這裡是為'CustomEvent'
myEvent.initEvent(
// 1. event_name: 事件名稱
// 2. canBubble: 是否冒泡
// 3. cancelable: 是否可以取消預設行為
)
createEvent
:建立一個事件initEvent
:初始化一個事件
可以看到,initEvent
可以指定3個引數。
(有些文章中會說還有第四個引數detail
,但是我檢視了W3C
上並沒有這個引數,而且實踐了一下也沒有效果)
「事件的監聽」
自定義事件的監聽其實和普通事件的一樣,使用addEventListener
來監聽:
button.addEventListener('event_name', function (e) {})
「事件的觸發」
觸發自定義事件使用dispatchEvent(myEvent)
。
注意⚠️,這裡的引數是要自定義事件的物件(也就是myEvent
),而不是自定義事件的名稱('myEvent'
)
「案例」
來看個案例吧:
// 1.
// let myEvent = new Event('myEvent');
// 2.
// let myEvent = new CustomEvent('myEvent', {
// detail: {
// name: 'lindaidai'
// }
// })
// 3.
let myEvent = document.createEvent('CustomEvent');
myEvent.initEvent('myEvent', true, true)
let btn = document.getElementsByTagName('button')[0]
btn.addEventListener('myEvent', function (e) {
console.log(e)
console.log(e.detail)
})
setTimeout(() => {
btn.dispatchEvent(myEvent)
}, 2000)
8. 冒泡和捕獲的具體過程
冒泡指的是:當給某個目標元素繫結了事件之後,這個事件會依次在它的父級元素中被觸發(當然前提是這個父級元素也有這個同名稱的事件,比如子元素和父元素都繫結了click
事件就觸發父元素的click
)。
捕獲則是從上層向下層傳遞,與冒泡相反。
(非常好記,你就想想水底有一個泡泡從下面往上傳的,所以是冒泡)
來看看這個例子:
<!-- 會依次執行 button li ul -->
<ul onclick="alert('ul')">
<li onclick="alert('li')">
<button onclick="alert('button')">點選</button>
</li>
</ul>
<script>
window.addEventListener('click', function (e) {
alert('window')
})
document.addEventListener('click', function (e) {
alert('document')
})
</script>
冒泡結果:button > li > ul > document > window
捕獲結果:window > document > ul > li > button
9. 所有的事件都有冒泡嗎?
並不是所有的事件都有冒泡的,例如以下事件就沒有:
onblur
onfocus
onmouseenter
onmouseleave
11. 描述下原型鏈
12. 手寫new
function myNew (fn, ...args) {
let instance = Object.create(fn.prototype);
let result = fn.call(instance, ...args)
return typeof result === 'object' ? result : instance;
}
13. typeof和instanceof的區別
typeof
表示是對某個變數型別的檢測,基本資料型別除了null
都能正常的顯示為對應的型別,引用型別除了函式會顯示為'function'
,其它都顯示為object
。
而instanceof
它主要是「用於檢測某個建構函式的原型物件在不在某個物件的原型鏈上」。
14. typeof為什麼對null錯誤的顯示
這只是 JS 存在的一個悠久 Bug。在 JS 的最初版本中使用的是 32 位系統,為了效能考慮使用低位儲存變數的型別資訊,000 開頭代表是物件然而 null 表示為全零,所以將它錯誤的判斷為 object 。
15. 詳細說下instanceof
instanceof
它主要是「用於檢測某個建構函式的原型物件在不在某個物件的原型鏈上」。
算了,直接手寫實現吧:
function myInstanceof (left, right) {
let proto = Object.getPrototypeOf(left);
while (true) {
if (proto === null) return false;
if (proto === right.prototype) return true;
proto = Object.getPrototypeOf(proto)
}
}
16. 一句話描述一下this
指向最後呼叫函式的那個物件,是函式執行時內部自動生成的一個內部物件,只能在函式內部使用
17. 函式內的this是在什麼時候確定的?
函式呼叫時,指向最後呼叫的那個物件
18. apply/call/bind的相同和不同
19. webpack中的loader和plugin有什麼區別
(答案參考童歐巴的一篇webpack
面試文章哦:「吐血整理」再來一打Webpack面試題(持續更新))
loader它是一個轉換器,只專注於轉換檔案這一個領域,完成壓縮、打包、語言編譯,「它僅僅是為了打包」。並且執行在打包之前。
而plugin是一個擴充套件器,它豐富了webpack本身,為其進行一些其它功能的擴充套件。「它不侷限於打包,資源的載入,還有其它的功能」。所以它是在整個編譯週期都起作用。
20. HTTP和TCP的不同
HTTP的責任是去定義資料,在兩臺計算機相互傳遞資訊時,HTTP規定了每段資料以什麼形式表達才是能夠被另外一臺計算機理解。
而TCP所要規定的是資料應該怎麼傳輸才能穩定且高效的傳遞與計算機之間。
(還可以再擴充套件)
21. TCP和UDP的區別
TCP是一個面向連線的、可靠的、基於位元組流的傳輸層協議。
UDP是一個面向無連線的傳輸層協議。
TCP為什麼可靠,是因為它有三次握手來保證雙方都有接受和傳送資料的能力。
位元組流服務:將大塊資料分割為以報文段為單位的資料包進行管理
22. 介紹一下虛擬DOM
虛擬DOM
本質就是用一個原生的JavaScript
物件去描述一個DOM
節點。是對真實DOM
的一層抽象。
由於在瀏覽器中操作DOM
是很昂貴的。頻繁的操作DOM
,會產生一定的效能問題,因此我們需要這一層抽象,在patch
過程中儘可能地一次性將差異更新到DOM
中,這樣保證了DOM
不會出現效能很差的情況。
另外還有很重要的一點,也是它的設計初衷,為了更好的跨平臺,比如Node.js
就沒有DOM
,如果想實現SSR
(服務端渲染),那麼一個方式就是藉助Virtual DOM
,因為Virtual DOM
本身是JavaScript
物件。
Vue2.x
中的虛擬DOM
主要是借鑑了snabbdom.js
,Vue3
中借鑑inferno.js
演算法進行優化。
23. 盒模型
24. 輸入URL到頁面的呈現
看三元的《(1.6w字)瀏覽器靈魂之問,請問你能接得住幾個?》
https://juejin.im/post/5df5bcea6fb9a016091def69
分別從網路,解析,渲染來說
面試的問題基本都答出來了,當然後面還有一個技術總監的電話面,主要是問了一些工作相關的問題。
其實這家公司開出的條件也挺讓呆呆心動的,包括氛圍感覺也挺好,只不過可能還不是自己想要的吧,所以最終也是沒去,挺可惜的...如果面試我的那位小哥哥哥看到了這裡,還請不要難過哈,我們江湖會再見的????。
深圳某房地產公司
4月27日
一面
5道筆試題
並詳細說一下前面三道
(額,呆呆能力有限只答出來了前面三道)
二面
1. JSON的原理以及手寫一個實現
基本原理:主要就是利用 script
標籤的src
屬性沒有跨域的限制,通過指向一個需要訪問的地址,由服務端返回一個預先定義好的 Javascript
函式的呼叫,並且將伺服器資料以該函式引數的形式傳遞過來,此方法需要前後端配合完成。
執行過程:
前端定義一個解析函式(如:
jsonpCallback = function (res) {}
)通過
params
的形式包裝script
標籤的請求引數,並且宣告執行函式(如cb=jsonpCallback
)後端獲取到前端宣告的執行函式(
jsonpCallback
),並以帶上引數且呼叫執行函式的方式傳遞給前端前端在
script
標籤返回資源的時候就會去執行jsonpCallback
並通過回撥函式的方式拿到資料了。
缺點:
只能進行
GET
請求
優點:
相容性好,在一些古老的瀏覽器中都可以執行
程式碼實現:
(具體可以看我的這篇文章:JSONP原理及實現:https://www.jianshu.com/p/88bb82718517)
<script>
function JSONP({
url,
params = {},
callbackKey = 'cb',
callback
}) {
// 定義本地的唯一callbackId,若是沒有的話則初始化為1
JSONP.callbackId = JSONP.callbackId || 1;
let callbackId = JSONP.callbackId;
// 把要執行的回撥加入到JSON物件中,避免汙染window
JSONP.callbacks = JSONP.callbacks || [];
JSONP.callbacks[callbackId] = callback;
// 把這個名稱加入到引數中: 'cb=JSONP.callbacks[1]'
params[callbackKey] = `JSONP.callbacks[${callbackId}]`;
// 得到'id=1&cb=JSONP.callbacks[1]'
const paramString = Object.keys(params).map(key => {
return `${key}=${encodeURIComponent(params[key])}`
}).join('&')
// 建立 script 標籤
const script = document.createElement('script');
script.setAttribute('src', `${url}?${paramString}`);
document.body.appendChild(script);
// id自增,保證唯一
JSONP.callbackId++;
}
JSONP({
url: 'http://localhost:8080/api/jsonps',
params: {
a: '2&b=3',
b: '4'
},
callbackKey: 'cb',
callback (res) {
console.log(res)
}
})
JSONP({
url: 'http://localhost:8080/api/jsonp',
params: {
id: 1
},
callbackKey: 'cb',
callback (res) {
console.log(res)
}
})
</script>
2. 瀏覽器為什麼要跨域?如果是因為安全的話那小程式或者其他的為什麼沒有跨域?
跨域的產生來源於現代瀏覽器所通用的同源策略
,所謂同源策略,是指只有在地址的:
協議名
域名
埠名
均一樣的情況下,才允許訪問相同的cookie、localStorage,以及訪問頁面的DOM
或是傳送Ajax
請求。若在不同源的情況下訪問,就稱為跨域。
例如以下為同源:
http://www.example.com:8080/index.html
http://www.example.com:8080/home.html
以下為跨域:
http://www.example.com:8080/index.html
http://www3.example.com:8080/index.html
注意⚠️:
但是有兩種情況:http
預設的埠號為80
,https
預設埠號為443
。
所以:
http://www.example.com:80 === http://www.example.com
https://www.example.com:443 === https://www.example.com
「為什麼瀏覽器會禁止跨域?」
「簡答」:
首先,跨域只存在於瀏覽器端,因為我們知道瀏覽器的形態是很開放的,所以我們需要對它有所限制。
其次,同源策略主要是為了保證使用者資訊的安全,可分為兩種:Ajax
同源策略和DOM
同源策略。
Ajax
同源策略主要是使得不同源的頁面不能獲取cookie
且不能發起Ajax
請求,這樣在一定程度上防止了CSRF
攻擊。
DOM
同源策略也一樣,它限制了不同源頁面不能獲取DOM
,這樣可以防止一些惡意網站在自己的網站中利用iframe
嵌入正規的網站並迷惑使用者,以此來達到竊取使用者資訊。
「深答」:
首先,跨域只存在於瀏覽器端。瀏覽器它為
web
提供了訪問入口,並且訪問的方式很簡單,在位址列輸入要訪問的地址或者點選某個連結就可以了,正是這種「開放的形態」,所以我們需要對它有所限制。所以同源策略它的產生主要是為了保證使用者資訊的安全,防止惡意的網站竊取資料。分為兩種:
Ajax
同源策略與DOM
同源策略:同源策略它算是瀏覽器安全的第一層屏障吧,因為就像
CSRF
攻擊,它只能限制不同源頁面cookie
的獲取,但是攻擊者還可能通過其它的方式來達到攻擊效果。(注,上面提到的
iframe
限制DOM
查詢,案例如下)// HTML <iframe name="yinhang" src="www.yinhang.com"></iframe> // JS // 由於沒有同源策略的限制,釣魚網站可以直接拿到別的網站的Dom const iframe = window.frames['yinhang'] const node = iframe.document.getElementById('你輸入賬號密碼的Input') console.log(`拿到了這個${node},我還拿不到你剛剛輸入的賬號密碼嗎`)
Ajax
同源策略它主要做了這兩種限制:1.不同源頁面不能獲取cookie
;2.不同源頁面不能發起Ajax
請求。我認為它是防止CSRF
攻擊的一種方式吧。因為我們知道cookie
這個東西它主要是為了解決瀏覽器與伺服器會話狀態的問題,它本質上是儲存在瀏覽器或本地檔案中一個小小的文字檔案,那麼它裡面一般都會儲存了使用者的一些資訊,包括隱私資訊。如果沒有Ajax
同源策略,惡意網站只需要一段指令碼就可以獲取你的cookie
,從而冒充你的身份去給其它網站傳送惡意的請求。DOM
同源策略也一樣,它限制了不同源頁面不能獲取DOM
。例如一個假的網站利用iframe
巢狀了一個銀行網站mybank.com,並把寬高或者其它部分調整的和原銀行網站一樣,僅僅只是位址列上的域名不同,若是使用者沒有注意的話就以為這個是個真的網站。如果這時候使用者在裡面輸入了賬號密碼,如果沒有同源策略,那麼這個惡意網站就可以獲取到銀行網站中的DOM
,也就能拿到使用者的輸入內容以此來達到竊取使用者資訊的攻擊。
參考:
https://segmentfault.com/a/1190000015597029
https://juejin.im/post/5cad99796fb9a068ab40a29a
3. CORS跨域的原理
跨域資源共享(CORS
)是一種機制,是W3C標準。它允許瀏覽器向跨源伺服器,發出XMLHttpRequest
或Fetch
請求。並且整個CORS
通訊過程都是瀏覽器自動完成的,不需要使用者參與。
而使用這種跨域資源共享
的前提是,瀏覽器必須支援這個功能,並且伺服器端也必須同意這種"跨域"
請求。因此實現CORS
的關鍵是伺服器需要伺服器。通常是有以下幾個配置:
「Access-Control-Allow-Origin」
「Access-Control-Allow-Methods」
「Access-Control-Allow-Headers」
「Access-Control-Allow-Credentials」
「Access-Control-Max-Age」
具體可看:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
過程分析:
「簡單回答」:
當我們發起跨域請求時,「如果是非簡單請求」,瀏覽器會幫我們自動觸發預檢請求,也就是 OPTIONS 請求,用於確認目標資源是否支援跨域。「如果是簡單請求,則不會觸發預檢,直接發出正常請求。」
瀏覽器會根據服務端響應的 header 自動處理剩餘的請求,如果響應支援跨域,則繼續發出正常請求,如果不支援,則在控制檯顯示錯誤。
「詳細回答」:
瀏覽器先根據同源策略對前端頁面和後臺互動地址做匹配,若同源,則直接傳送資料請求;若不同源,則傳送跨域請求。
伺服器收到瀏覽器跨域請求後,根據自身配置返回對應檔案頭。若未配置過任何允許跨域,則檔案頭裡不包含
Access-Control-Allow-origin
欄位,若配置過域名,則返回Access-Control-Allow-origin + 對應配置規則裡的域名的方式
。瀏覽器根據接受到的 響應頭裡的
Access-Control-Allow-origin
欄位做匹配,若無該欄位,說明不允許跨域,從而丟擲一個錯誤;若有該欄位,則對欄位內容和當前域名做比對,如果同源,則說明可以跨域,瀏覽器接受該響應;若不同源,則說明該域名不可跨域,瀏覽器不接受該響應,並丟擲一個錯誤。
在CORS
中有簡單請求
和非簡單請求
,簡單請求是不會觸發CORS
的預檢請求的,而非簡單請求會。
“需預檢的請求”
要求必須首先使用 OPTIONS
方法發起一個預檢請求到伺服器,以獲知伺服器是否允許該實際請求。"預檢請求“的使用,可以避免跨域請求對伺服器的使用者資料產生未預期的影響。
(關於更多CORS的內容可以看我的另一篇文章:CORS原理及實現:https://www.jianshu.com/p/b2bdf55e1bf5)
4. CORS預請求OPTIONS就一定是安全的嗎?
5. 在深圳的網頁上輸入百度,是怎麼把這個請求發到北京的
這個當時面試官和我說的是,中間會經過很多的站點,比如會經過湖南,或者其它城市,由各個城市的這些站點一層一層分發下去。
6. 輸入URL到頁面的呈現
7. Vue的響應式原理
8. 那在這個響應式中一個資料改變它是怎麼通知要更新的,也就是如何把資料和頁面關聯起來?
面的最慘的一次...因為這次面試是當天下午6點才去面的,在這之前呆呆已經經過了3輪面試的折磨,所以身心疲憊很不在狀態。當然最主要的是自己確實準備的還不夠充分,其實現在回過頭來看看這些題都不太難的...
當天也小小的自閉了一下,整理好狀態第二天好好總結吧 ????。
深圳某海外直播公司
4月28日
(當時是電話面,一個小時20分鐘,問了我大概五六十道題,我能想到的一共是50題,還有一些記不起來了)
1. CommonJS和ES6模組的區別
CommonJS模組是執行時載入,ES6 Modules是編譯時輸出介面
CommonJS輸出是值的拷貝;ES6 Modules輸出的是值的引用,被輸出模組的內部的改變會影響引用的改變
CommonJs匯入的模組路徑可以是一個表示式,因為它使用的是
require()
方法;而ES6 Modules只能是字串CommonJS
this
指向當前模組,ES6 Modulesthis
指向undefined
且ES6 Modules中沒有這些頂層變數:
arguments
、require
、module
、exports
、__filename
、__dirname
關於第一個差異,是因為CommonJS 載入的是一個物件(即module.exports
屬性),該物件只有在指令碼執行完才會生成。而 ES6 模組不是物件,它的對外介面只是一種靜態定義,在程式碼靜態解析階段就會生成。
(具體可以看我的這篇文章:https://juejin.im/post/5eaacd175188256d4345ea3a)
2. 模組的非同步載入
模組的非同步載入可以使用AMD
或者CMD
規範。
(具體可以看我的這篇文章:https://juejin.im/post/5eaacd175188256d4345ea3a)
3. 開發一個模組要考慮哪些問題?
封閉開放式原則、安全性
(應該還有,但是沒想到)
4. 實現一個一組非同步請求按順序執行你有哪些方法?
利用
reduce
,初始值傳入一個Promise.resolve()
,之後往裡面不停的疊加.then()
。(類似於這裡https://juejin.im/post/5e58c618e51d4526ed66b5cf#heading-51)利用
forEach
,本質和reduce
原理相同。(類似於這裡https://juejin.im/post/5e58c618e51d4526ed66b5cf#heading-53)還可以用
ES9
中的for...await...of
來實現。
5. Promise.all()是併發的還是序列的?
併發的。不過Promise.all().then()
結果中陣列的順序和Promise.all()
接收到的陣列順序一致。
6. 平時寫過哪些正規表示式
之前有用過用正則去除輸入框的首尾空格,正規表示式為:
var trimReg = /(^\s+)|(\s+$)/g
;不過後來由於Vue
中有一個修飾符.trim
,使用起來更方便(如v-model.trim="msg"
)就用這種方式多一些;再或者也可以用ES10
新出的trimStart
和trimEnd
來去除首尾空格。用於校驗手機號的正則:
var phoneReg = /^1[3456789]\d{9}$/g
。用正則寫一個根據name獲取cookie中的值的方法:
function getCookie(name) {
var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]*)'));
if (match) return unescape(match[2]);
}
詳細介紹可以看這裡:每日一題-JS篇-根據name獲取cookie中值的方法:https://github.com/LinDaiDai/niubility-coding-js/blob/master/%E6%AF%8F%E6%97%A5%E4%B8%80%E9%A2%98/%E6%AF%8F%E6%97%A5%E4%B8%80%E9%A2%98-JS%E7%AF%87.md#%E7%94%A8%E6%AD%A3%E5%88%99%E5%86%99%E4%B8%80%E4%B8%AA%E6%A0%B9%E6%8D%AEname%E8%8E%B7%E5%8F%96cookie%E4%B8%AD%E7%9A%84%E5%80%BC%E7%9A%84%E6%96%B9%E6%B3%95
7. 正則裡的非如何實現的
^
要是放在[]
裡的話就表示"除了^後面的內容都能匹配"
,也就是非的意思。
例如:
(除了l
,其它都變成了"帥"
)
var str = 'lindaidai';
console.log(str.replace(/[^l]/g, '帥'));
// l帥帥帥帥帥帥帥帥
反之,如果是不在[]
裡的話則表示開頭匹配:
(只有l
變成了"帥"
)
var str = 'lindaidai';
console.log(str.replace(/^l/g, '帥'));
8. webpack幾種hash的實現原理
hash
是跟整個專案的構建相關,只要專案裡有檔案更改,整個專案構建的hash
值都會更改,並且全部檔案都共用相同的hash
值。(粒度整個專案)chunkhash
是根據不同的入口進行依賴檔案解析,構建對應的chunk
(模組),生成對應的hash
值。只有被修改的chunk
(模組)在重新構建之後才會生成新的hash
值,不會影響其它的chunk
。(粒度entry
的每個入口檔案)contenthash
是跟每個生成的檔案有關,每個檔案都有一個唯一的hash
值。當要構建的檔案內容發生改變時,就會生成新的hash
值,且該檔案的改變並不會影響和它同一個模組下的其它檔案。(粒度每個檔案的內容)
(具體可以看我簡書上的這篇文章:https://www.jianshu.com/p/486453d81088)
這裡只是說明了三種hash
的不同...至於原理暫時沒了解。
9. webpack如果使用了hash命名,那是每次都會重寫生成hash嗎
這個問題在上一個問題中已經說明了,要看webpack
的配置。
有三種情況:
如果是
hash
的話,是和整個專案有關的,有一處檔案發生更改則所有檔案的hash
值都會發生改變且它們共用一個hash
值;如果是
chunkhash
的話,只和entry
的每個入口檔案有關,也就是同一個chunk
下的檔案有所改動該chunk
下的檔案的hash
值就會發生改變如果是
contenthash
的話,和每個生成的檔案有關,只有當要構建的檔案內容發生改變時才會給該檔案生成新的hash
值,並不會影響其它檔案。
10. webpack中如何處理圖片的?
在webpack
中有兩種處理圖片的loader
:
file-loader
:解決CSS
等中引入圖片的路徑問題;(解決通過url
,import/require()
等引入圖片的問題)url-loader
:當圖片小於設定的limit
引數值時,url-loader
將圖片進行base64
編碼(當專案中有很多圖片,通過url-loader
進行base64
編碼後會減少http
請求數量,提高效能),大於limit引數值,則使用file-loader
拷貝圖片並輸出到編譯目錄中;
詳細使用可以檢視這裡:霖呆呆的webpack之路-loader篇:https://github.com/LinDaiDai/niubility-coding-js/blob/master/%E5%89%8D%E7%AB%AF%E5%B7%A5%E7%A8%8B%E5%8C%96/webpack/%E9%9C%96%E5%91%86%E5%91%86%E7%9A%84webpack%E4%B9%8B%E8%B7%AF-loader%E7%AF%87.md#file-loader
11. 說一下回流和重繪
「迴流」:
觸發條件:
當我們對 DOM 結構的修改引發 DOM 幾何尺寸變化的時候,會發生迴流
的過程。
例如以下操作會觸發迴流:
一個 DOM 元素的幾何屬性變化,常見的幾何屬性有
width
、height
、padding
、margin
、left
、top
、border
等等, 這個很好理解。使 DOM 節點發生
增減
或者移動
。讀寫
offset
族、scroll
族和client
族屬性的時候,瀏覽器為了獲取這些值,需要進行迴流操作。呼叫
window.getComputedStyle
方法。
迴流過程:由於DOM的結構發生了改變,所以需要從生成DOM這一步開始,重新經過樣式計算
、生成佈局樹
、建立圖層樹
、再到生成繪製列表
以及之後的顯示器顯示這整一個渲染過程走一遍,開銷是非常大的。
「重繪」:
觸發條件:
當 DOM 的修改導致了樣式的變化,並且沒有影響幾何屬性的時候,會導致重繪
(repaint
)。
重繪過程:由於沒有導致 DOM 幾何屬性的變化,因此元素的位置資訊不需要更新,所以當發生重繪的時候,會跳過生存佈局樹
和建立圖層樹
的階段,直接到生成繪製列表
,然後繼續進行分塊、生成點陣圖等後面一系列操作。
「如何避免觸發迴流和重繪」:
避免頻繁使用 style,而是採用修改
class
的方式。將動畫效果應用到
position
屬性為absolute
或fixed
的元素上。也可以先為元素設定
display: none
,操作結束後再把它顯示出來。因為在display
屬性為none
的元素上進行的DOM操作不會引發迴流和重繪使用
createDocumentFragment
進行批量的 DOM 操作。對於 resize、scroll 等進行防抖/節流處理。
避免頻繁讀取會引發迴流/重繪的屬性,如果確實需要多次使用,就用一個變數快取起來。
利用 CSS3 的
transform
、opacity
、filter
這些屬性可以實現合成的效果,也就是CPU
加速。
參考來源:https://juejin.im/post/5df5bcea6fb9a016091def69#heading-57
12. 盒模型及如何轉換
box-sizing: content-box
(W3C盒模型,又名標準盒模型):元素的寬高大小表現為內容的大小。
box-sizing: border-box
(IE盒模型,又名怪異盒模型):元素的寬高表現為內容 + 內邊距 + 邊框的大小。背景會延伸到邊框的外沿。
13. 實現水平垂直居中的幾種方式
這裡我是按照子弈的總結答的:https://juejin.im/post/5d690c726fb9a06b155dd40d#heading-81
Flex佈局(子元素是塊級元素)
.box {
display: flex;
width: 100px;
height: 100px;
background-color: pink;
}
.box-center{
margin: auto;
background-color: greenyellow;
}
Flex佈局
.box {
display: flex;
width: 100px;
height: 100px;
background-color: pink;
justify-content: center;
align-items: center;
}
.box-center{
background-color: greenyellow;
}
絕對定位實現(定位元素定寬定高)
.box {
position: relative;
height: 100px;
width: 100px;
background-color: pink;
}
.box-center{
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
margin: auto;
width: 50px;
height: 50px;
background-color: greenyellow;
}
14. flex的相容性怎樣
「簡單回答:」
IE6~9
不支援,IE10~11
部分支援flex的2012版
,但是需要-ms-
字首。
其它的主流瀏覽器包括安卓和IOS
基本上都支援了。
「詳細回答:」
IE10部分支援2012,需要-ms-字首
Android4.1/4.2-4.3部分支援2009 ,需要-webkit-字首
Safari7/7.1/8部分支援2012, 需要-webkit-字首
IOS Safari7.0-7.1/8.1-8.3部分支援2012,需要-webkit-字首
15. 你知道到哪裡檢視相容性嗎
可以到Can I use
上去檢視,官網地址為:https://caniuse.com/
16. 移動端中css你是使用什麼單位
「比較常用的」:
em
:定義字型大小時以父級的字型大小為基準;定義長度單位時以當前字型大小為基準。例父級font-size: 14px
,則子級font-size: 1em;
為font-size: 14px;
;若定義長度時,子級的字型大小如果為14px
,則子級width: 2em;
為width: 24px
。rem
:以根元素的字型大小為基準。例如html
的font-size: 14px
,則子級1rem = 14px
。%
:以父級的寬度為基準。例父級width: 200px
,則子級width: 50%;height:50%;
為width: 100px;height: 100px;
vw和vh
:基於視口的寬度和高度(視口不包括瀏覽器的位址列工具欄和狀態列)。例如視口寬度為1000px
,則60vw = 600px;
vmin和vmax
:vmin
為當前vw
和vh
中較小的一個值;vmax
為較大的一個值。例如視口寬度375px
,視口高度812px
,則100vmin = 375px;
,100vmax = 812px;
「不常用的:」
ex和ch
:ex
以字元"x"
的高度為基準;例如1ex
表示和字元"x"
一樣長。ch
以數字"0"
的寬度為基準;例如2ch
表示和2個數字"0"
一樣長。
「移動端佈局總結」:
移動端佈局的方式主要使用rem和flex,可以結合各自的優點,比如flex佈局很靈活,但是字型的大小不好控制,我們可以使用rem和媒體查詢控制字型的大小,媒體查詢視口的大小,然後不同的上視口大小下設定設定html的font-size。
可單獨製作移動端頁面也可響應式pc端移動端共用一個頁面。沒有好壞,視情況而定,因勢利導
(總結來源:玲瓏)
17. rem和em的區別
「em:」
定義字型大小時以父級的字型大小為基準;定義長度單位時以當前字型大小為基準。例父級font-size: 14px
,則子級font-size: 1em;
為font-size: 14px;
;若定義長度時,子級的字型大小如果為14px
,則子級width: 2em;
為width: 24px
。
「rem:」
以根元素的字型大小為基準。例如html
的font-size: 14px
,則子級1rem = 14px
。
18. 在移動端中怎樣初始化根元素的字型大小
一個簡易版的初始化根元素字型大小。
頁面開頭處引入下面這段程式碼,用於動態計算font-size
:
(假設你需要的1rem = 20px
)
(function () {
var html = document.documentElement;
function onWindowResize() {
html.style.fontSize = html.getBoundingClientRect().width / 20 + 'px';
}
window.addEventListener('resize', onWindowResize);
onWindowResize();
})();
document.documentElement
:獲取document
的根元素html.getBoundingClientRect().width
:獲取html
的寬度(視窗的寬度)監聽
window
的resize
事件
一般還需要配合一個meta
頭:
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-sacle=1.0, maximum-scale=1.0, user-scalable=no" />
19. 移動端中不同手機html預設的字型大小都是一樣的嗎
如果沒有人為去改變根元素字型大小的話,預設是1rem = 16px
;根元素預設的字型大小是16px
。
20. 你做過哪些動畫效果
實話實說沒太做過。
21. 如果讓你實現一個一直旋轉的動畫你會如何做
css程式碼:
<style>
.box {
width: 100px;
height: 100px;
background-color: red;
animation: spin 2s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg) }
to { transform: rotate(360deg) }
}
</style>
html程式碼:
<div class="box"></div>
22. animation介紹一下
語法:
animation: name duration timing-function delay iteration-count direction;
值 | 描述 |
---|---|
animation-name | 規定需要繫結到選擇器的 keyframe 名稱。(mymove) |
animation-duration | 規定完成動畫所花費的時間,以秒或毫秒計。(2s) |
animation-timing-function | 規定動畫的速度曲線。(ease|linear|ease-in|cubic-bezier(n,n,n,n)) |
animation-delay | 規定在動畫開始之前的延遲。(2s) |
animation-iteration-count | 規定動畫應該播放的次數。(n | infinite) n次/無限 |
animation-direction | 規定是否應該輪流反向播放動畫。(normal | alternate) 正常/反向 |
23. animation有一個steps()功能符知道嗎?
一句話介紹:steps()
功能符可以讓動畫不連續。
地位和作用:和貝塞爾曲線(cubic-bezier()
修飾符)一樣,都可以作為animation
的第三個屬性值。
和貝塞爾曲線的區別:貝塞爾曲線像是滑梯且有4個關鍵字(引數),而steps
像是樓梯坡道且只有number
和position
兩個關鍵字。
語法:
steps(number, position)
number: 數值,表示把動畫分成了多少段
position: 表示動畫是從時間段的開頭連續還是末尾連續。支援
start
和end
兩個關鍵字,含義分別如下:start
:表示直接開始。end
:表示戛然而止。是預設值。
具體可以看這裡:https://www.zhangxinxu.com/wordpress/2018/06/css3-animation-steps-step-start-end/
24. 用過哪些移動端的除錯工具
Chrome
瀏覽器 ->more tools
->Remote devices
->chrome://inspect/#devices
Mac
+IOS
+Safari
25. 說一下原型鏈
26. 詳細說一下instanceof
27. V8的垃圾回收是發生在什麼時候?
V8引擎幫助我們實現了自動的垃圾回收管理,「利用瀏覽器渲染頁面的空閒時間進行垃圾回收。」
28. 具體說一下垃圾回收機制
(這裡我用的是:https://juejin.im/post/5e8b261ae51d4546c0382ab4#heading-20 裡的總結)
「棧記憶體的回收:」
棧記憶體呼叫棧上下文切換後就被回收,比較簡單。
「堆記憶體的回收:」
V8的堆記憶體分為新生代記憶體和老生代記憶體,新生代記憶體是臨時分配的記憶體,存在時間短,老生代記憶體存在時間長。
新生代記憶體回收機制:
新生代記憶體容量小,64位系統下僅有32M。新生代記憶體分為「From、To」兩部分,進行垃圾回收時,先掃描From,將非存活物件回收,將存活物件順序複製到To中,之後調換From/To,等待下一次回收
老生代記憶體回收機制
「晉升」:如果新生代的變數經過多次回收依然存在,那麼就會被放入老生代記憶體中
「標記清除」:老生代記憶體會先遍歷所有物件並打上標記,然後對正在使用或被強引用的物件取消標記,回收被標記的物件
「整理記憶體碎片」:把物件挪到記憶體的一端
(當然想要詳細瞭解的話也可以看我的這篇文章:JavaScript進階-記憶體機制(表情包初探))
29. 在專案中如何把http的請求換成https
由於我在專案中是會對axios
做一層封裝,所以每次請求的域名也是寫在配置檔案中,有一個baseURL
欄位專門用於儲存它,所以只要改這個欄位就可以達到替換所有請求http
為https
了。
當然後面我也有了解到:
利用meta
標籤把http
請求換為https
:
<meta http-equiv ="Content-Security-Policy" content="upgrade-insecure-requests">
30. 知道meta標籤有把http換成https的功能嗎?
參考上一題????。
31. http請求可以怎麼攔截
在瀏覽器和伺服器進行傳輸的時候,可以被nginx
代理所攔截,也可以被閘道器攔截。
32. https的加密方式
HTTPS主要是採用對稱金鑰加密和非對稱金鑰加密組合而成的混合加密機制進行傳輸。
也就是傳送密文的一方用"對方的公鑰"進行加密處理"對稱的金鑰",然後對方在收到之後使用自己的私鑰進行解密得到"對稱的金鑰",這在確保雙發交換的金鑰是安全的前提下使用對稱金鑰方式進行通訊。
33. 混合加密的好處
對稱金鑰加密和非對稱金鑰加密都有它們各種的優缺點,而混合加密機制就是將兩者結合利用它們各自的優點來進行加密傳輸。
比如既然對稱金鑰的優點是加解密效率快,那麼在客戶端與服務端確定了連線之後就可以用它來進行加密傳輸。不過前提是得解決雙方都能安全的拿到這把對稱金鑰。這時候就可以利用非對稱金鑰加密來傳輸這把對稱金鑰,因為我們知道非對稱金鑰加密的優點就是能保證傳輸的內容是安全的。
所以它的好處是即保證了對稱金鑰能在雙方之間安全的傳輸,又能使用對稱加密方式進行通訊,這比單純的使用非對稱加密通訊快了很多。以此來解決了HTTP中內容可能被竊聽的問題。
其它HTTP相關的問題:
如:
HTTPS的工作流程
混合加密機制的好處
數字簽名
ECDHE握手和RSA握手
向前安全性
這些問題都可以看到我的這篇文章:HTTPS面試問答:https://github.com/LinDaiDai/niubility-coding-js/blob/master/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/HTTPS%E9%9D%A2%E8%AF%95%E9%97%AE%E7%AD%94.md
34. 瀏覽器如何驗證伺服器的身份
這道題主要可以從數字簽名
和數字證照
上來答。
當時我答的時候就把證照的頒發流程
、HTTPS
數字證照的驗證過程完整的說了一遍就算過了。
具體可以看「HTTPS面試」????問答中的第5、6、7
問。
35. ETag首部欄位說一下
這個無非就是配合If-None-Match
來達到一個協商快取
的作用。值為伺服器某個資源的唯一標識。
具體可以看我的這篇文章:霖呆呆你來說說瀏覽器快取吧
36. 你們的token一般是存放在哪裡的
Token
其實就是「訪問資源的憑證」。
一般是使用者通過使用者名稱和密碼登入成功之後,伺服器將登陸憑證做數字簽名,加密之後得到的字串作為token
。
它在使用者登入成功之後會返回給客戶端,客戶端主要有這麼幾種儲存方式:
儲存在
localStorage
中,每次呼叫介面的時候都把它當成一個欄位傳給後臺儲存在
cookie
中,讓它自動傳送,不過缺點就是不能跨域拿到之後儲存在
localStorage
中,每次呼叫介面的時候放在HTTP
請求頭的Authorization
欄位裡
(很明顯我答的不夠專業,歡迎補充,感謝????)
37. token會不會被偽造?
(很明顯我答的不夠專業,歡迎補充,感謝????)
38. redis中一般用來存什麼
使用者登入成功之後的一些資訊
(很明顯我答的不夠專業,歡迎補充,感謝????)
39. 前後端如何驗證一個使用者是否下線了
(很明顯我答的不夠專業,歡迎補充,感謝????)
40. CSP白名單知道嗎?
(很明顯我答的不夠專業,歡迎補充,感謝????)
41. nginx有配置過嗎?
只會配置一些跨域方面的問題。
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://localhost:8887;
add_header Access-Control-Allow-Origin *;
}
}
}
利用ngnix跨域的關鍵就是在配置檔案中設定server
項,然後設定其中的location
屬性,proxy_pass
:需要代理的伺服器地址,add_header:給響應報文中新增首部欄位,例如Access-Control-Allow-Origin
設定為*
,即允許所有的請求源請求。
具體可以看:Yiming君-面試題:nginx有配置過嗎?反向代理知道嗎?
https://juejin.im/post/5eb0f8aaf265da7ba65f7ba2
42. 反向代理知道嗎?
我們將請求傳送到伺服器,然後伺服器對我們的請求進行轉發,我們只需要和代理伺服器進行通訊就好。所以對於客戶端來說,是感知不到伺服器的。
43. 有用過抓包工具嗎?
唔...沒有...
44. 你平常用的電腦是Mac嗎?
(...在電話那頭默默的點頭)
45. Fiddler有用過嗎?
唔...知道...
46. Vue的diff演算法
這裡我是按照:
https://mp.weixin.qq.com/s/2xyP4jVevuXrGov_VsWfvA
中的第13題答的。
47. Vue中computed和methods的區別
48. 例如要獲取當前時間你會放到computed還是methods裡?
放在methods
中,因為computed
會有惰性,並不能知道new Date()
的改變。
49. 你們的許可權功能是怎麼做的?
小小的寫了一篇文章,可以看這裡:資料許可權如何控制
https://github.com/LinDaiDai/niubility-coding-js/blob/master/other/%E6%95%B0%E6%8D%AE%E6%9D%83%E9%99%90%E5%A6%82%E4%BD%95%E6%8E%A7%E5%88%B6.md
50. 那你在判斷許可權的時候是用的字串匹配還是位運算?
和麵試官扯了一堆我資料許可權判斷的具體過程,其中可能有多個許可權:並的情況000011110001&000011110002
,或的情況000011110001|000011110002
,以及如何做的許可權匹配。最後面試官:
"所以那還是用的字串匹配咯?"
尬...我比較low
...用的字串匹配...
(哇,真的絕了...1個小時20分鐘50多道題,答的我口渴????,不過也可以看出有很多移動端的我都沒有答上來,面試官也表示理解,畢竟我主要是以PC端為主,所以竟然也算是過了,很感謝這位面試官細心的幫我分析一些問題)
後來有了解這位面試官近期也跳槽去騰訊了,果然面完呆呆之後他就去大廠了,好人一生平安????????。
深圳某國內直播公司
這家公司其實是上家公司的總部,因為面完上家之後,HR也知道我的顧慮,想要去一個大點的團隊,所以就把我推薦去了他們的總部。非常Nice的HR小姐姐,好感動,就算你看不到我的文章,我也還是要感謝你 ????。
5月8日
一面(前端副總監)
1. 輸入URL到頁面呈現
(必問...)
看三元的《(1.6w字)瀏覽器靈魂之問,請問你能接得住幾個?》
https://juejin.im/post/5df5bcea6fb9a016091def69
分別從網路,解析,渲染來說
2. 為什麼說script標籤建議放在body下面?
JS
程式碼在載入完之後是立即執行的,且JS
程式碼執行時會阻塞頁面的渲染。
3. 為什麼說script標籤會阻塞頁面的渲染呢?渲染執行緒和js引擎執行緒不是分開的嗎?
JS屬於單執行緒,當我們在載入script
標籤內容的時候,渲染執行緒會被暫停,因為script
標籤裡可能會操作DOM
的,所以如果你載入script
標籤又同時渲染頁面肯定就衝突了,因此說渲染執行緒(GUI
)和js引擎執行緒互斥。
4. 協商快取說一下
Last-Modefied
配合If-Modified-Since
ETag
配合If-None-Match
也是個常見的問題了,不瞭解的小夥伴可以看我的這篇文章:霖呆呆你來說說瀏覽器快取吧
(當時面試官還重複了一下我說的這4個頭部欄位,自己回顧了一下我說的對不對,好可愛~)
5. HTTP中的Keep-Alive有了解過嗎?
Keep-Alive
是HTTP
的一個頭部欄位Connection
中的一個值,它是保證我們的HTTP
請求能建立一個持久連線。也就是說建立一次TCP
連線即可進行多次請求和響應的互動。它的特點就是隻要有一方沒有明確的提出斷開連線,則保持TCP
連線狀態,減少了TCP
連線和斷開造成的額外開銷。
另外,在HTTP/1.1
中所有的連線預設都是持久連線的,但是HTTP/1.0
並未標準化。
6. 跨域有了解嗎?如何解決跨域?
我工作中碰到主要是利用CORS
來解決跨域問題,說了一下它的原理以及後臺需要如何做。
另外說到了JSONP
的原理,以及它的優點:相容性好;缺點:只能進行GET
請求,且有安全問題。
還有說到了ngnix
反向代理來解決跨域。
CORS原理及實現:https://www.jianshu.com/p/b2bdf55e1bf5
JSONP原理及實現:https://www.jianshu.com/p/88bb82718517
面試題:nginx有配置過嗎?反向代理知道嗎?:https://juejin.im/post/5eb0f8aaf265da7ba65f7ba2
其它的,我當時說我有看過一篇文章裡面詳細的介紹10多種跨域解決方案,但是自己沒有過多的去了解。
哈哈,其實也就是秋風大大的這篇文章10種跨域解決方案(附終極大招)
7. WebSocket有了解過嗎?它也可以跨域的
這個當時答的沒用過。
我知道它是能使得客戶端和伺服器之間存在持久的連線,而且雙方都可以隨時開始傳送資料,這種方式本質沒有使用 HTTP 的響應頭,因此也沒有跨域的限制。
(多的不會了)
8. 前端安全方面?XSS?CSRF?
(必問...)
(以下回答參考子弈小哥哥的面試分享:兩年工作經驗成功面試阿里P6總結:https://juejin.im/post/5d690c726fb9a06b155dd40d#heading-60
以及蔡徐坤小哥哥的2萬字 | 前端基礎拾遺90問:https://juejin.im/post/5e8b261ae51d4546c0382ab4#heading-48
「XSS」
XSS(Cross Site Script)跨站指令碼攻擊。指的是攻擊者向網頁注入惡意的客戶端程式碼,通過惡意的指令碼對客戶端網頁進行篡改,從而在使用者瀏覽網頁時,對使用者瀏覽器進行控制或者獲取使用者隱私資料的一種攻擊方式。
主要是分為三種:
「儲存型」:即攻擊被儲存在服務端,常見的是在評論區插入攻擊指令碼,如果指令碼被儲存到服務端,那麼所有看見對應評論的使用者都會受到攻擊。
「反射型」:攻擊者將指令碼混在URL裡,服務端接收到URL將惡意程式碼當做引數取出並拼接在HTML裡返回,瀏覽器解析此HTML後即執行惡意程式碼
「DOM型」:將攻擊指令碼寫在URL中,誘導使用者點選該URL,如果URL被解析,那麼攻擊指令碼就會被執行。和前兩者的差別主要在於DOM型攻擊不經過服務端
如何防禦XSS攻擊
「輸入檢查」:對輸入內容中的
script
和<iframe>
等標籤進行轉義或者過濾「設定httpOnly」:很多XSS攻擊目標都是竊取使用者cookie偽造身份認證,設定此屬性可防止JS獲取cookie
「開啟CSP」,即開啟白名單,可阻止白名單以外的資源載入和執行
「CSRF」
CSRF攻擊(Cross-site request forgery)跨站請求偽造。是一種劫持受信任使用者向伺服器傳送非預期請求的攻擊方式,通常情況下,它是攻擊者藉助受害者的 Cookie 騙取伺服器的信任,但是它並不能拿到Cookie,也看不到Cookie的內容,它能做的就是給伺服器傳送請求,然後執行請求中所描述的命令,以此來改變伺服器中的資料,也就是並不能竊取伺服器中的資料。
防禦主要有三種:
驗證Token
:瀏覽器請求伺服器時,伺服器返回一個token,每個請求都需要同時帶上token和cookie才會被認為是合法請求
驗證Referer
:通過驗證請求頭的Referer來驗證來源站點,但請求頭很容易偽造
設定SameSite
:設定cookie的SameSite,可以讓cookie不隨跨站請求發出,但瀏覽器相容不一
「點選挾持」
誘使使用者點選看似無害的按鈕(實則點選了透明 iframe 中的按鈕).
監聽滑鼠移動事件,讓危險按鈕始終在滑鼠下方.
使用 HTML5 拖拽技術執行敏感操作(例如 deploy key).
預防策略:
服務端新增 X-Frame-Options 響應頭,這個 HTTP 響應頭是為了防禦用 iframe 巢狀的點選劫持攻擊。這樣瀏覽器就會阻止嵌入網頁的渲染。
JS 判斷頂層視口的域名是不是和本頁面的域名一致,不一致則不允許操作,
top.location.hostname === self.location.hostname
;敏感操作使用更復雜的步驟(驗證碼、輸入專案名稱以刪除)。
(這個來源於LuckyWinty: http://www.imooc.com/article/295400)
9. setTimeout的執行原理(EventLoop)
(必問...)
(回答參考:https://juejin.im/post/5e621f5fe51d452700567c32)
setTimeout
的執行機制:執行該語句時,是立即把當前定時器程式碼推入事件佇列,當定時器在事件列表中滿足設定的時間值時將傳入的函式加入任務佇列,之後的執行就交給任務佇列負責。但是如果此時任務佇列不為空,則需等待,所以執行定時器內程式碼的時間可能會大於設定的時間
說了一下它屬於非同步任務,然後說了一下還有哪些巨集任務以及微任務,最後說了一下EventLoop
的執行過程。
一開始整個指令碼作為一個巨集任務執行
執行過程中同步程式碼直接執行,巨集任務進入巨集任務佇列,微任務進入微任務佇列
當前巨集任務執行完出隊,檢查微任務列表,有則依次執行,直到全部執行完
執行瀏覽器UI執行緒的渲染工作
檢查是否有
Web Worker
任務,有則執行執行完本輪的巨集任務,回到2,依此迴圈,直到巨集任務和微任務佇列都為空
(具體可以看這裡:https://juejin.im/post/5e58c618e51d4526ed66b5cf#heading-1)
10. requestAnimationFrame有了解過嗎?
(啪啪啪,不長記性,其實之前面試有被問過,但是忘了再去了解了,這就吃虧了,沒答上來)
requestAnimationFrame
是瀏覽器用於定時迴圈操作的一個介面,類似於setTimeout
,主要用途是按幀對網頁進行重繪。對於JS
動畫,用requestAnimationFrame
會比 setInterval
效果更好。
具體可以看:https://juejin.im/post/5e621f5fe51d452700567c32
11. requestAnimationFrame和setTimeout的區別?
同上...
12. 平常工作中ES6+主要用到了哪些?
(下面看著很多,但我肯定不是全答哈,挑了幾個來回答)
ES6
:
Class
模組
import
和export
箭頭函式
函式預設引數
...
擴充套件運輸符允許展開陣列解構
字串模版
Promise
let const
Proxy、Map、Set
物件屬性同名能簡寫
ES7
:
includes
**
求冪運算子
ES8
:
async/await
Object.values()和Object.entries()
padStart()和padEnd()
Object.getOwnPropertyDescriptors()
函式引數允許尾部
,
ES9
:
for...await...of
...
展開符合允許展開物件收集剩餘引數Promise.finally()
正則中的四個新功能
ES10
:
flat()
flatMap()
fromEntries()
trimStart
和trimEnd
matchAll
BigInt
try/catch
中報錯允許沒有err
異常引數Symbol.prototype.description
Function.toString()
呼叫時呈現原本原始碼的樣子
還不瞭解的小夥伴可以看看浪裡哥的這篇:盤點ES7、ES8、ES9、ES10新特性
https://juejin.im/post/5dda2b5e6fb9a07a83691766
13. 如何在前端實現一個圖片壓縮
實話實話沒做過,但是後來面試官告訴我:可以使用canvas
來實現。具體做法等我寫篇文章哈。
(當時我還反問了一句面試官:那批量圖片壓縮要怎麼做呢?把他驚的...然後他和我說挺複雜的...
16. 專案中有碰到什麼難的問題嗎?如何解決的?
例舉了我最經典的bpmn.js
,以此來引出我寫了很多關於這方面的教材,以及建立了微信群,為國內的bpmn.js
社群貢獻了一份力量...怎麼高大上怎麼來...
當然也有提到我GitHub
上的bpmn-chinese-document
專案只有100
多的Star
,他說理解,畢竟這東西用的人不是很多。
17. 期望薪資多少?
喊了個挺高的數,老哥笑了笑,你這個工作年限我們可能給不到,然後扯了點別的。
18. 還有什麼想要問我的嗎?
團隊人員分佈情況
技術棧
我進去主要是負責哪塊內容
年終獎/季度獎
調薪的頻率以及幅度
加班多不多
(其實後面這些問題應該是等到HR面的時候問的,但是感覺和麵試官挺聊的來的我就先打聽了)
二面(CTO)
1. JSONP的實現原理
絕了...又來
2. XSS攻擊以及如何預防?
絕了...又來X2
3. 不使用框架如何實現元件按需載入以及原理
當時答的是是用import
來按需引入,以及提到了Vue.use
。
但後來有去了解,babel-plugin-import
就可以實現。
4. 你們這個是自己寫的元件庫嗎?
估計面試官看錯了...雖然我的專案有個元件庫的功能,但是是基於Ant Design of Vue
二次開發的。
面試推薦好文
面試分享:兩年工作經驗成功面試阿里P6總結:https://juejin.im/post/5d690c726fb9a06b155dd40d
2萬字 | 前端基礎拾遺90問:https://juejin.im/post/5e8b261ae51d4546c0382ab4
一位前端小姐姐的五萬字面試寶典https://juejin.im/post/5e91b01651882573716a9b23
藝術喵 2 年前端面試心路歷程(位元組跳動、YY、虎牙、BIGO)| 掘金技術徵文:https://juejin.im/post/5e85ec79e51d4547153d0738
一年半經驗前端社招7家大廠&獨角獸全過經歷 | 掘金技術徵文:https://juejin.im/post/5e8d5a48f265da47ce6cb21f
面試完50個人後我寫下這篇總結:https://juejin.im/post/5df1e312f265da33d039d06d
(1.6w字)瀏覽器靈魂之問,請問你能接得住幾個?: https://juejin.im/post/5df5bcea6fb9a016091def69
(還有很多大佬的很多好文,不是呆呆不寫在這裡啊,是因為呆呆暫時只刷了這些,抱歉了????)
後語
你盼世界,我盼望你無bug
。這篇文章就介紹到了這裡。
我是一隻正在努力求生存的呆呆,也在這條路上不斷的總結和成長,希望自己能夠堅持✊。
"風浪沒平息 我宣告奔跑的意義"
"這不是叛逆 我只是淋了一場雨"
喜歡「霖呆呆」的小夥還希望可以關注霖呆呆的公眾號 LinDaiDai
我會不定時的更新一些前端方面的知識內容以及自己的原創文章????
你的鼓勵就是我持續創作的主要動力 ????.
相關文章
- Spring面試題總結的很全面,附帶超詳細答案Spring面試題
- Linux面試題彙總答案Linux面試題
- 最新PHP面試題彙總(附答案)PHP面試題
- ASP net core面試題彙總及答案面試題
- JavaScript常見面試題彙總(含答案)JavaScript面試題
- Java常見面試題及答案彙總Java面試題
- 21年最新Python面試題及答案彙總詳解(上)Python面試題
- 經典Java面試題彙總及答案解析Java面試題
- Web前端面試題目及答案彙總Web前端面試題
- Zookeeper應用場景彙總(超詳細)
- 面試寶典:15道MyBatis 常見面試題彙總及答案MyBatis面試題
- 記錄近期面試題,面試總結面試題
- Java 後端 100多道面試題,多看點題,沒壞處!Java後端面試題
- 技術乾貨:Tomcat面試題彙總及答案Tomcat面試題
- 技術乾貨:Kotlin面試題彙總及答案Kotlin面試題
- 【半月刊】前端高頻面試題及答案彙總前端面試題
- 附答案!超全SpringBoot面試題總結Spring Boot面試題
- 2022年最新資料庫經典面試題及答案彙總(含PostgreSQL、Oracle、MySQL)資料庫面試題OracleMySql
- 技術乾貨:spring cloud面試題彙總及答案SpringCloud面試題
- 技術乾貨:Kubernetes面試題彙總及答案面試題
- 【半月刊 3】前端高頻面試題及答案彙總前端面試題
- 【半月刊 2】前端高頻面試題及答案彙總前端面試題
- 【半月刊 4】前端高頻面試題及答案彙總前端面試題
- 100個 iOS 程式設計師面試題彙總iOS程式設計師面試題
- java面試題總結-詳細分類Java面試題
- 超詳細的Java面試題總結(四 )之JavaWeb基礎知識總結Java面試題Web
- 100道JAVA面試題+JAVA面試題參考答案Java面試題
- 2017年前端面試題整理彙總100題前端面試題
- 【BAT機器學習面試題】前100題彙總及勘誤(上)BAT機器學習面試題
- 超詳細的Java面試題總結(三)之Java集合篇常見問題Java面試題
- iOS 面試題彙總iOS面試題
- mysql 面試題彙總MySql面試題
- vue面試題總彙Vue面試題
- java面試題彙總Java面試題
- LLM面試題彙總面試題
- (轉)2017年前端面試題整理彙總100題前端面試題
- NET近期面試總結和麵試題面試
- Dubbo面試25題答案詳解面試