本文只記錄面試過程中遇到的面試題(不定更),答案請自行百度(自己動手、豐衣足食)
框架知識
1.談談對ssr的瞭解
seo與首屏渲染快 比較適合首屏使用ssr進行快速渲染,更利於seo
2.vue資料驅動的原理
1.vue在例項化過程中,遍歷data所有的屬性並使用Object.defineProperty將屬性全轉化為getter/setter
2.每個例項物件都有一個watcher,在模板編譯過程中使用getter訪問data的屬性,並且標記為依賴,建立檢視與資料的聯絡
3.當依賴的資料發生了變化,就呼叫了setter方法,watcher會對比前後兩個值的變化,決定是否通知檢視重新渲染
4.v-if和v-show的區別
1.DOM差異,CSS差異
5.Proxy 相比於 defineProperty 的優勢
- 陣列變化也能監聽到
- 不需要深度遍歷監聽
6.nextTick()
官方解釋:在下次 DOM 更新迴圈結束之後執行延遲迴調。在修改資料之後立即使用這個方法,獲取更新後的 DOM。
何時使用:(DOM發生變化的操作(不嚴謹!!!具體看下面兩個例子???))
-
1.在created()鉤子函式進行的DOM操作一定要放在Vue.nextTick()的回撥函式中。 原因:是在created()鉤子函式執行的時候DOM 其實並未進行任何渲染,所以一定要將DOM操作的js程式碼放進Vue.nextTick()的回撥函式中。mounted該鉤子函式執行時所有的DOM掛載和渲染都已完成,因此不需要使用nextTick()。
-
2.在資料變化後要執行的某個操作,而這個操作需要使用隨資料改變而改變的DOM結構的時候,這個操作應該放進Vue.nextTick()的回撥函式中。
7.vue的生命週期
參考本文,個人感覺寫的比較詳細了 segmentfault.com/a/119000001… 也可參考本文,講的比較精幹https://juejin.im/post/5c64d15d6fb9a049d37f9c20#heading-60
微信小程式
1.簡述微信小程式原理?
- 1.微信小程式採用JavaScript、WXML、WXSS三種技術進行開發
- 2.小程式分為兩個部分webview和appService。其中webview主要用來展現UI,appService有來處理業務邏輯、資料及介面呼叫。它們在兩個程式中執行,通過系統層JSBridge實現通訊,實現UI的渲染、事件的處理
2.rpx(responsivepixel)
微信小程式新定義了一個尺寸單位,可以適配不同解析度的螢幕,它規定螢幕寬為750rpx,如在 iPhone6 上,螢幕寬度為375px,共有750個物理畫素,則750rpx = 375px =750物理畫素,1rpx = 0.5px = 1物理畫素。
3.wx.navigateTo(Object object)
保留當前頁面。但小程式中頁面棧最多十層。
4.生命週期
- 1.onLaunch小程式初始化完成時(全域性只觸發一次)
- 2.onLoad頁面載入時觸發。一個頁面只會呼叫一次
- 3.onShow頁面顯示/切入前臺時觸發。
- 4.onReady頁面初次渲染完成時觸發。一個頁面只會呼叫一次,代表頁面已經準備妥當,可以和檢視層進行互動。
- 5.onHide頁面隱藏/切入後臺時觸發。
- 6.onUnload頁面解除安裝時觸發
{% asset_img mina-lifecycle.png mina-lifecycle %}
非框架知識
1.serviceworker
參考本文https://www.cnblogs.com/dojo-lzz/p/8047336.html
2.哪些方式導致記憶體洩漏
- 1.意外的全域性變數: 無法被回收
- 2.定時器: 未被正確關閉,導致所引用的外部變數無法被釋放
- 3.事件監聽: 沒有正確銷燬 (低版本瀏覽器可能出現)
- 4.閉包: 會導致父級中的變數無法被釋放
- 5.dom 引用: dom 元素被刪除時,記憶體中的引用未被正確清空
3.本地儲存及區別
這裡重點討論IndexedDB和WebSQL:參考本文加以理解http://www.cnblogs.com/ljwsyt/p/9760266.html
4.閉包、作用及處理,垃圾回收器
概念:
-
- 作為一個函式變數的一個引用,當函式返回時,其處於啟用狀態。
-
- 一個閉包就是當一個函式返回時,一個沒有釋放資源的棧區。
作用:
- 實現封裝,管理私有變數和私有方法,將變數(狀態)的變化封裝在安全的環境中
弊端:
- 讓變數始終保持在記憶體中,不被釋放,記憶體消耗會很大
處理:
- 使用後的變數置為Null,等待垃圾回收器回收
垃圾回收器:兩種方式:1.標記清除(主要)2.引用計數
5.按需載入(webpack)
參考本文https://segmentfault.com/a/1190000011519350
1.import():
{
path: '/hello',
name: 'Hello',
// component: Hello
component: import(/* webpackChunkName: 'Hello' */ '../components/Hello')
}
複製程式碼
2.require.ensure():多個路由指定相同的chunkName,會合並打包成一個js檔案。
{
path: '/hello',
name: 'Hello',
// component: Hello
component: resolve => require.ensure([], () => resolve(require('../components/Hello')), 'demo')
}
複製程式碼
7.css動畫和js動畫的區別
參考本文https://www.cnblogs.com/simba-lkj/p/6139066.html
8.cdn的原理,哪些東西可以使用cdn
介紹:
- 經策略性部署的整體系統,解決由於網路頻寬小、使用者訪問量大、網點分佈不均而產生的使用者訪問網站響應速度慢的問題。
目的:
- 在現有的Internet中增加一層新的網路架構,將網站的內容釋出到最接近使用者的網路“邊緣”,使使用者可以就近取得所需的內容,解決 Internet 網路擁塞狀況,提高使用者訪問網站的響應速度。
9.深拷貝和淺拷貝的區別
參考本文https://www.cnblogs.com/echolun/p/7889848.html
- 淺拷貝:一層遍歷和Object.assign()
深拷貝主要針對引用型別,拷貝所有層級的屬性
- 方法一:遞迴實現深拷貝
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{};
if(obj && typeof obj==="object"){
for(key in obj){
if(obj.hasOwnProperty(key)){
//判斷ojb子元素是否為物件,如果是,遞迴複製
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{
//如果不是,簡單複製
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
let a=[1,2,3,4],
b=deepClone(a);
a[0]=2;
console.log(a,b);
複製程式碼
- 方法二:JSON.Parse和JSON.stringify(相容ie8+,對於正規表示式型別和函式型別無法深拷貝,會直接丟失相應的值,而且會拋棄物件的constructer)
function deepClone(obj){
let _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone
}
let a=[0,1,[2,3],4],
b=deepClone(a);
a[0]=1;
a[2][0]=1;
console.log(a,b);
複製程式碼
10.Map和WeakMap與Object
ES6新的資料結構,更為完善的hash結構
與Object的區別:
- Map的鍵可以是個各種型別的數值,但Object只能是字串型別或Symbol型別
Map與WeakMap的區別:
- WeakMap只接受物件作為鍵名,鍵名是物件的弱引用,當物件被回收後,WeakMap自動移除對應的鍵值對,WeakMap結構有助於防止記憶體洩漏。
11.Set和WeakSet
Set集合,沒有重複元素的集合,WeakSet的鍵必須為物件
11.有哪幾種繼承
- 1.原型鏈繼承:將父類的例項作為子類的原型
- 2.構造繼承:使用父類的建構函式來增強子類例項,等於是複製父類的例項屬性給子類(沒用到原型)
- 3.例項繼承:為父類例項新增新特性,作為子類例項返回
- 4.拷貝繼承
- 5.組合繼承:通過呼叫父類構造,繼承父類的屬性並保留傳參的優點,然後通過將父類例項作為子類原型,實現函式複用
- 6.寄生組合繼承:通過寄生方式,砍掉父類的例項屬性,這樣,在呼叫兩次父類的構造的時候,就不會初始化兩次例項方法/屬性,避免的組合繼承的缺點
- 7.ES6的Class繼承
12.跨越的處理方案
- 解決協議,域名,埠不用的問題
- 1、 通過
jsonp
跨域 (只支援get
)- 2、
document.domain
+iframe
跨域(僅限主域相同,子域不同的跨域應用場景)- 3、
window.name
+iframe
跨域- 3.1name值在不同的頁面(甚至不同域名)載入後依舊存在,並且可以支援非常長的 name 值(2MB)。
- 4、 postMessage跨域
- 5、 跨域資源共享(CORS)
Access-Control-Allow-Origin
- 5.1普通跨域請求:只服務端設定Access-Control-Allow-Origin即可,前端無須設定,
- 5.2若要帶cookie請求:前後端都需要設定。
- 6、 nginx代理跨域
- 7、 nodejs中介軟體代理跨域
- 8、 Vue跨域:(proxy)
13.重繪和迴流
-
重繪(repaint): 當元素樣式的改變不影響佈局時,瀏覽器將使用重繪對元素進行更新,此時由於只需要UI層面的重新畫素繪製,因此 損耗較少
-
迴流(reflow): 當元素的尺寸、結構或觸發某些屬性時,瀏覽器會重新渲染頁面,稱為迴流。此時,瀏覽器需要重新經過計算,計算後還需要重新頁面佈局,因此是較重的操作。會觸發迴流的操作
15.效能優化
1.減少HTTP請求數
- 1.資源合併與壓縮
- 2.圖片Sprites
- 3.HTTP快取
2.
script
指令碼置底(或defer
)
3.
web worker
4.迴流重繪
2.伺服器快取策略
-
Cache-Control/Expires:瀏覽器判斷快取是否過期,未過期時,直接使用強快取,如果同時出現,Cache-Control的 max-age 優先順序高於 Expires
-
協商快取:唯一標識
Etag
和If-None-Match
、最後一次修改時間Last-Modified
和If-Modified-Since
(Etag優先順序高於Lst-Modifieds)
19.sea和require的區別、優缺點
最大的區別:
- SeaJS對模組的態度是懶執行, 而RequireJS對模組的態度是預執行
RequireJS:(1)實現js檔案的非同步載入,避免網頁失去響應; (2)管理模組之間的依賴性,便於程式碼的編寫和維護。
21.web worker
簡而言之就是子執行緒,本質就是資料重新整理和頁面渲染不產生衝突,可通過自帶的訊息機制進行通訊但是弊端是相容性不好,而且無法達到像websocket輪詢的效果
22.箭頭函式什麼情況下不能用(需要動態上下文的場景)
- 1.定義物件方法
- 2.定義原型方法
- 3.定義事件回撥函式
- 4.定義建構函式
- 5.刻意追求過短的程式碼,可能會給程式碼閱讀和邏輯理解帶來困難。
23.rem和em的區別
區別:
- rem是基於html元素的字型大小來決定,
- em則根據使用它的元素的大小決定(很多人錯誤以為是根據父類元素,實際上是使用它的元素繼承了父類的屬性才會產生的錯覺)
舉例: 當使用 rem 單位,他們轉化為畫素大小取決於頁根元素的字型大小,即 html 元素的字型大小。 根元素字型大小乘以你 rem 值。 例如,根元素的字型大小 16px,10rem 將等同於 160px,即 10 x 16 = 160。
當使用em單位時,畫素值將是em值乘以使用em單位的元素的字型大小。 弊端:繼承
24.移動端適配
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;">
複製程式碼
2.手淘團隊flexible.js佈局
25.陣列如何去重(ES5,ES6)
1.ES6中新增了Set資料結構,類似於陣列,但是 它的成員都是唯一的 ,其建構函式可以接受一個陣列作為引數
2.ES6中Array新增了一個靜態方法Array.from,可以把類似陣列的物件轉換為陣列
ES6:
let array = [1,2,3,4,4,2,1,5];
let res = Array.from(new Set(array))
console.log(res)
複製程式碼
ES5方法一
function unique(arr) {
return arr.filter(function(item, index, arr) {
//當前元素,在原始陣列中的第一個索引==當前索引值,否則返回當前元素
return arr.indexOf(item, 0) === index
})
}
複製程式碼
ES5方法二
function uniqueArr(arr){
var arr2 = []
var len = arr.length
for(var i=0;i<len; i++) {
if(arr2.indexOf(arr[i]) === -1) {
arr2.push(arr[i])
}
}
return arr2
}
複製程式碼
26.函式柯里化
柯里化是指這樣一個函式(假設叫做createCurry),他接收函式A作為引數,執行後能夠返回一個新的函式。並且這個新的函式能夠處理函式A的剩餘引數。 詳情參考https://www.jianshu.com/p/5e1899fe7d6b
27.vue的虛擬dom原理是什麼?怎麼實現的?
js建立dom,diff演算法,同級比較
28.http請求頭裡都有什麼內容
- Accept:瀏覽器能夠處理的內容型別
- Accept-Charset:瀏覽器能夠顯示的字符集
- Accept-Encoding:瀏覽器能夠處理的壓縮編碼
- Accept-Language:瀏覽器當前設定的語言
- Connection:瀏覽器與伺服器之間連線的型別
- Cookie:當前頁面設定的任何Cookie
- Host:發出請求的頁面所在的域
- Referer:發出請求的頁面的URL
- User-Agent:瀏覽器的使用者代理字串
29.常用狀態碼
- 200: 成功,並返回資料
- 302: 臨時重定向
- 304: 資源未修改,可使用快取
- 403: 拒絕請求
- 404: 資源不存在
- 500: 伺服器錯誤
29.promise順序執行
- 方法一: then()執行
- 方法二: 使用佇列執行
- 方法三: 使用async、await實現類似同步程式設計
30.Event loop
首先放上參考文章,非常推薦,簡單明瞭!!!juejin.im/post/59e85e…
概念: 簡單來講就是時間迴圈機制(廢話,哈哈哈哈哈~~~~)
首先看一下下面這張圖,有助於理解js是如何執行的 {% asset_img eventloop.png eventloop %}
上圖表達的意思就是:???
- 同步和非同步任務分別進入不同的執行"場所",同步的進入主執行緒,非同步的進入Event Table並註冊函式。
- 當指定的事情完成時,Event Table會將這個函式移入Event Queue。
- 主執行緒內的任務執行完畢為空,(js引擎存在monitoring process程式,會持續不斷的檢查主執行緒執行棧是否為空,一旦為空,就會去Event Queue那裡檢查是否有等待被呼叫的函式。)會去Event Queue讀取對應的函式,進入主執行緒執行。
- 上述過程會不斷重複,也就是常說的Event Loop(事件迴圈)。
除了廣義的同步任務和非同步任務,我們對任務有更精細的定義:
- macro-task(巨集任務):包括整體程式碼script,IO,setTimeout,setInterval
- micro-task(微任務):Promise中的回撥(Promise自身是巨集任務,不知是否可以這麼理解),process.nextTick {% asset_img task-step.png task-step %}
30.call apply bind區別和用法
都是為了改變某個函式執行時的上下文而存在的(就是為了改變函式內部this的指向);
- apply的第二個引數是一個陣列,
- call第二個及以後的引數都是陣列中的元素
- bind與apply、call最大的區別就是:bind不會立即呼叫,其他兩個會立即呼叫
31.THIS(看完你就明白了)
this 就是你 call 一個函式時,傳入的第一個引數。(請務必背下來「this 就是 call 的第一個引數」)
參考本文,一看就懂https://zhuanlan.zhihu.com/p/23804247
32.原型與原型鏈
原型鏈:
- 在JavaScript中萬物都是物件,物件和物件之間也有關係,並不是孤立存在的。物件之間的繼承關係,在JavaScript中是通過prototype物件指向父類物件,直到指向Object物件為止,這樣就形成了一個原型指向的鏈條
原理:
- 當我們訪問物件的一個屬性或方法時,它會先在物件自身中尋找,如果有則直接使用,如果沒有則會去原型物件中尋找,如果找到則直接使用。如果沒有則去原型的原型中尋找,直到找到Object物件的原型,Object物件的原型沒有原型,如果在Object原型中依然沒有找到,則返回undefined。
方法:
- 使用物件的hasOwnProperty()來檢查物件自身是否含有該屬性,使用in來檢查是否在整條原型鏈上是否含有該屬性
注意點:
- Object是JS中所有物件資料型別的基類(最頂層的類)在Object.prototype上沒有__proto__這個屬性。
33.GraphQL
詳情請關注官網連結http://graphql.cn/
概念:一種用於 API 的查詢語言,代替rest api
34.node登陸註冊
- bcrypt
- jwt
- passport
- passport-jwt
35.node 中介軟體
參考https://zhuanlan.zhihu.com/p/30384677
36.JWT
中間用點分隔開,並且都會使用 Base64 編碼
- 1.header(頭部)
- 2.payload(資料)
- 3.signature(簽名)
37.JsBridge的核心
- 1.用途:實現Native與Js相互呼叫的功能
- 2.核心:
- 1.攔截Url
- 2.load url("javascript:js_method()");
演算法
1.氣泡排序
function bubleSort(arr) {
var len = arr.length;
for (let i = len ; i >= 2;i--) {
for(let j = 0; j <= i - 1; j++) {
if(arr[j] > arr[j + 1]) {
// [arr[j],arr[j+1]] = [arr[j+1],arr[j]]
let tmp = arr[j+1]
arr[j+1] = arr[j]
arr[j] = tmp
}
}
}
return arr;
}
複製程式碼
2.快速排序 原理:選一個數,比較大小,放在當前數的左右陣列,最後遞迴左右陣列
function quickSort(arr) {
if(arr.length <= 1) {
return arr; //遞迴出口
}
var left = [],
right = [],
current = arr.splice(0,1);
for(let i = 0; i < arr.length; i++) {
if(arr[i] < current) {
left.push(arr[i]) //放在左邊
} else {
right.push(arr[i]) //放在右邊
}
}
return quickSort(left).concat(current,quickSort(right));
}
複製程式碼