記錄本人在廣州面試中遇到的一些問題(主要是技術一面),公司中小企業居多,也有大廠(非BAT)。崗位一般寫的中級前端開發或1~3年經驗崗位。問題主要選取一些高頻和基礎的問題。(問題的回答只是本人的理解,非參考答案,有些答案只給個提示,詳解可谷歌百度或在掘金內搜尋相關文章)
題目
- 考察頻率指相關問題的考察頻率,並非只是提到的點。
JavaScript基礎
1、宣告提升類問題 (考察頻率:高)
變數宣告和函式宣告都會提升,但函式會提升到變數前。 具體解釋可參考《你不知道的JavaScript(上卷)》
2、js儲存方式(考察頻率:中)
- cookie
- sessionStorage
- localStorage
- indexedDB
3、什麼情況下會遇到跨域,怎麼解決?(考察頻率:高)
- 同源策略是瀏覽器的一個安全功能,不同源的客戶端指令碼在沒有明確授權的情況下,不能讀寫對方資源。若地址裡面的協議、域名和埠號均相同則屬於同源。
- jsonp跨域、nginx反向代理、node.js中介軟體代理跨域、後端設定http header、後端在伺服器上設定cors。
4、Promise中的執行順序(考察頻率:高)
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
promise.then(function() {
console.log('resolved.');
});
console.log('Hi!');
// Promise
// Hi!
// resolved
複製程式碼
上面程式碼中,Promise 新建後立即執行,所以首先輸出的是Promise。然後,then方法指定的回撥函式,將在當前指令碼所有同步任務執行完才會執行,所以resolved最後輸出。
5、JavaScript事件迴圈機制相關問題(考察頻率:高)
- 事件迴圈機制的概念
關鍵字:單執行緒非阻塞、執行棧、事件佇列、巨集任務(setTimeout()、setInterval())、微任務(new Promise())
可參考: zhuanlan.zhihu.com/p/33058983
- 巨集任務、微任務、同步任務的執行順序
setTimeout(function () {
console.log(1);
});
new Promise(function(resolve,reject){
console.log(2)
resolve(3)
}).then(function(val){
console.log(val);
})
console.log(4);
// 2
// 4
// 3
// 1
複製程式碼
先按順序執行同步任務,Promise新建後立即執行輸出2,接著輸出4,非同步任務等同步任務執行完後執行,且同一次事件迴圈中,微任務永遠在巨集任務之前執行。這時候執行棧空了,執行事件佇列,先取出微任務,輸出3,最後取出一個巨集任務,輸出1。
6、for迴圈中的作用域問題(考察頻率:高)
寫出以下程式碼輸出值,嘗試用es5和es6的方式進行改進輸出迴圈中的i值。
for (var i=1; i<=5; i++) {
setTimeout(function timer() {
console.log(i);
}, i*1000);
}
複製程式碼
- 輸出5個6,因為回撥函式在for迴圈之後執行,所有函式共享一個i的引用。
- es5:
for (var i=1; i<=5; i++) {
(function(j) {
setTimeout(function timer() {
console.log(j);
}, j*1000);
})(i);
}
複製程式碼
- es6:
for (let i=1; i<=5; i++) {
setTimeout(function timer() {
console.log(i);
}, i*1000);
}
複製程式碼
7、閉包的作用(考察頻率:中)
閉包的目的是外部函式可以訪問內部函式的作用域(區域性作用域)。比如訪問到內部作用域的變數。
8、原型及原型鏈(考察頻率:中)
參考小冊《Web 前端面試指南與高頻考題解析》
原型的理解
- 所有的引用型別(陣列、物件、函式),都具有物件特性,即可自由擴充套件屬性(null除外)
- 所有的引用型別(陣列、物件、函式),都有一個__proto__屬性,屬性值是一個普通的物件
- 所有的函式,都有一個prototype屬性,屬性值也是一個普通的物件
- 所有的引用型別(陣列、物件、函式),__proto__屬性值指向它的建構函式的prototype屬性值
原型鏈的理解
一段程式碼如下:
// 建構函式
function Foo(name, age) {
this.name = name
}
Foo.prototype.alertName = function () {
alert(this.name)
}
// 建立示例
var f = new Foo('zhangsan')
f.printName = function () {
console.log(this.name)
}
// 測試
f.printName()
f.alertName()
f.toString()
複製程式碼
因為f本身沒有toString(),並且f.__proto__(即Foo.prototype)中也沒有toString。當試圖得到一個物件的某個屬性時,如果這個物件本身沒有這個屬性,那麼會去它的__proto__(即它的建構函式的prototype)中尋找。
如果在f.__proto__中沒有找到toString,那麼就繼續去f.__proto__.__proto__中尋找,因為f.__proto__就是一個普通的物件而已嘛!
f.__proto__即Foo.prototype,沒有找到toString,繼續往上找 f.__proto__.__proto__即Foo.prototype.__proto__。Foo.prototype就是一個普通的物件,因此Foo.prototype.__proto__就是Object.prototype,在這裡可以找到toString。 因此f.toString最終對應到了Object.prototype.toString 這樣一直往上找,你會發現是一個鏈式的結構,所以叫做“原型鏈”。如果一直找到最上層都沒有找到,那麼就宣告失敗,返回undefined。最上層是什麼 —— Object.prototype.__proto__ === null
9、重繪和迴流(考察頻率:中)
- 重繪:當頁面中元素樣式的改變並不影響它在文件流中的位置時(例如:color、background-color、visibility等),瀏覽器會將新樣式賦予給元素並重新繪製它,這個過程稱為重繪。
- 迴流:當Render Tree(DOM)中部分或全部元素的尺寸、結構、或某些屬性發生改變時,瀏覽器重新渲染部分或全部文件的過程稱為迴流。
- 迴流要比重繪消耗效能開支更大。
- 迴流必將引起重繪,重繪不一定會引起迴流。
- 參考:juejin.im/post/5a9923…
10、實現一個深拷貝(思路)(考察頻率:中)
物件中可能又存在物件,所以需要深拷貝。首先需要知道這是一個遞迴呼叫,然後要判斷一些特殊型別(陣列,正則物件,函式)進行具體的操作,可以通過Object.prototype.toString.call(obj)進行判斷。
11、js浮點數運算精度問題(0.1+0.2!==0.3)
比如在 JavaScript 中計算 0.1 + 0.2時,到底發生了什麼呢?
首先,十進位制的0.1和0.2都會被轉換成二進位制,但由於浮點數用二進位制表達時是無窮的,例如。
JavaScript 程式碼:
0.1 -> 0.0001100110011001...(無限)
0.2 -> 0.0011001100110011...(無限)
IEEE 754 標準的 64 位雙精度浮點數的小數部分最多支援 53 位二進位制位,所以兩者相加之後得到二進位制為:
JavaScript 程式碼:
0.0100110011001100110011001100110011001100110011001100
因浮點數小數位的限制而截斷的二進位制數字,再轉換為十進位制,就成了 0.30000000000000004。所以在進行算術計算時會產生誤差。
參考:blog.csdn.net/helloxiaoli…
瀏覽器相關
12、瀏覽器從載入到渲染的過程,比如輸入一個網址到顯示頁面的過程。 (考察頻率:高)
載入過程:
- 瀏覽器根據 DNS 伺服器解析得到域名的 IP 地址
- 向這個 IP 的機器傳送 HTTP 請求
- 伺服器收到、處理並返回 HTTP 請求
- 瀏覽器得到返回內容
渲染過程:
- 根據 HTML 結構生成 DOM 樹
- 根據 CSS 生成 CSSOM
- 將 DOM 和 CSSOM 整合形成 RenderTree
- 根據 RenderTree 開始渲染和展示
- 遇到<script>時,會執行並阻塞渲染
13、瀏覽器快取機制(策略)(考察頻率:中)
14、效能優化(考察頻率:中)
參考小冊《Web 前端面試指南與高頻考題解析》
優化的方向有兩個:
- 減少頁面體積,提升網路載入
- 優化頁面渲染
減少頁面體積,提升網路載入
- 靜態資源的壓縮合並(JS 程式碼壓縮合並、CSS 程式碼壓縮合並、雪碧圖)
- 靜態資源快取(資源名稱加 MD5 戳)
- 使用 CDN 讓資源載入更快
優化頁面渲染
- CSS 放前面,JS 放後面
- 懶載入(圖片懶載入、下拉載入更多)
- 減少DOM 查詢,對 DOM 查詢做快取
- 減少DOM 操作,多個操作儘量合併在一起執行(DocumentFragment)
- 事件節流
- 儘早執行操作(DOMContentLoaded)
- 使用 SSR 後端渲染,資料直接輸出到 HTML 中,減少瀏覽器使用 JS - 模板渲染頁面 HTML 的時間
Vue
15、元件通訊方式 (考察頻率:高)
1)父->子
-
props(v-bind)
-
$refs
2)子->父
-
events(v-on)
-
$parent $root
3)非父子元件
-
event bus
-
vuex
16、雙向繫結原理(考察頻率:高)
網上各種文章很多,原理可以講淺也可以講深,看面試官自己的瞭解程度和他想考察的深度。 最基本的要講清楚資料劫持Object.defineProperty(), 講清楚依賴收集(Watcher、Dep)。
17、路由導航鉤子(導航守衛)(考察頻率:中)
- 全域性鉤子
- 路由獨享鉤子
- 元件內鉤子
看文件:router.vuejs.org/zh-cn/advan…
18、v-if和v-show的共同點和區別(考察頻率:中)
參考官方文件
都是用來做條件渲染,通過條件控制元素的顯示與隱藏。
v-if 是“真正”的條件渲染,因為它會確保在切換過程中條件塊內的事件監聽器和子元件適當地被銷燬和重建。
v-if 也是惰性的:如果在初始渲染時條件為假,則什麼也不做——直到條件第一次變為真時,才會開始渲染條件塊。
相比之下,v-show 就簡單得多——不管初始條件是什麼,元素總是會被渲染,並且只是簡單地基於 CSS 進行切換。
一般來說,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷。因此,如果需要非常頻繁地切換,則使用 v-show 較好;如果在執行時條件很少改變,則使用 v-if 較好。
總結
面試第一看眼緣,其次看實力,面試官覺得你自信,跟公司的崗位匹配,就會推薦你。