大家好,我是若川。祝大家中秋節快樂。最近組織了源碼共讀活動《1個月,200+人,一起讀了4周源碼》,已經有超50+人提交了筆記,群里已經有超1200人,感興趣的可以點此鏈接掃碼加我微信?ruochuan12?參與。
本文經作者@lxcan 授權轉載,未經授權請勿直接轉載。
原文標題:《三年經驗前端社招——騰訊微保》
原文鏈接:https://zhuanlan.zhihu.com/p/405640455
文末點擊閱讀原文
直達
前言
本人畢業學校是雙非二本,非計算機科班出身,大學時自學的前端相關技能。截止2021年8月,有3年前端開發經驗,技術棧為 vue 全家桶,求職意向城市是深圳。想著找一個更大的平臺尋求發展(技術沉淀、漲薪),所以出來接受社會的毒打了。。。
本文的目的是記錄自己的面試經歷,各位路過的兄dei也可以參考一下,也讓自己有個回顧和反思。路漫漫其修遠兮,吾將上下而求索
下面的題目,都會標明每一題的性質,部分題目也會給出一些參考思路和參考回答,希望各位大佬不吝賜教~
描述:對概念、過程的描述,純理論性問答題為主
舉例:說出應用場景,或者是自己團隊實踐的情況
偽代碼:寫代碼,但不需要跑起來,甚至可以隨便寫偽代碼,主要目的是描述思路
編程:真正的寫代碼,需要跑起來,有測試用例,要看到效果
HR面的話,是一些日常、項目回顧(少說技術細節)、職業規劃、你的優勢和缺點、為什么跑路、為什么選擇這邊、目前薪資和職級、期望薪資,HR面基本離不開這些問題。
一面
1、微信小程序,內嵌H5怎么和原生小程序通信【描述】
小程序 web-view 組件支持事件:bindload binderror bindmessage
web-view 網頁中可使用JSSDK 1.3.2 提供的接口返回小程序頁面:wx.miniProgram.reLaunch
,H5向小程序發消息:wx.miniProgram.postMessage
2、小程序分包開發怎么做【描述】【舉例】
通過在 app.json 的 subpackages 字段聲明項目分包結構:
{"subpackages":?[{"root":?"packageA","pages":?["pages/cat","pages/dog"]},{"root":?"packageB","name":?"pack2","pages":?["pages/apple","pages/banana"]}]
}
聲明 subpackages 后,將按 subpackages 配置路徑進行打包,subpackages 配置路徑外的目錄將被打包到 app(主包) 中
app(主包)也可以有自己的 pages(即最外層的 pages 字段)
subpackage 的根目錄不能是另外一個 subpackage 內的子目錄
tabBar 頁面必須在 app(主包)內
3、做過哪些性能優化【描述】
4、h5首頁加速項目,怎么衡量優化結果是否達到預期【描述】
5、h5頁面,頁面緩存(html)、資源緩存(js,css),微信長緩存怎么解決【描述】
針對html的緩存
(1)利用服務端設置response Headers, 強制讓HTML文件,每次都向服務器端強制校驗文件有效性~
cache-control:?max-age=0
Last-Modified:?Fri,05?Jun?2020?09:52:12?GMT
ETag:?W/"5e5asdfs-98dc"
(2)當前鏈接路徑加井號時間戳
對于JS和CSS靜態文件【取以下兩種方案其一即可】
(1)在引用時加上動態版本號,例如 <script src="index.js?v=2.5.0" />
(2)動態命名問題,例如利用webpack等打包工具生成HASH文件名 <script src="index.12321312.js" />
6、寫個函數,判斷一個字符串是否為手機靚號,手機靚號條件:有3個連續相同的數字如 '111' 或者 有4個依次遞增1的數字 '1234'【編程】
解法1:枚舉
將所有可能的靚號規則存入數組,逐一判斷,擴展性較差,如果不是4位就難搞
解法2:正則
function?isGoodPhone?(phone)?{let?phoneReg?=?/^1\d{10}$/;let?reg1?=?/(.)\1{2,}/g;let?reg2?=?/(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)){3}/g;return?phoneReg.test(phone)?&&?(reg1.test(phone)?||?reg2.test(phone));
}
7、算法,寫一個排序算法【編程】
//?冒泡排序
//?該算法的操作次數是一個等差數列?n?+?(n?-?1)?+?(n?-?2)?+?1?,去掉常數項以后得出時間復雜度是?O(n?*?n)
function?bubble(arr)?{if?(!arr?instanceof?Array)?return?arr;arr?=?arr.slice();for?(let?i?=?arr.length?-?1;?i?>?0;?i--)?{for?(let?j?=?0;?j?<?i;?j++)?{if?(arr[j]?>?arr[j?+?1])?{[arr[j],?arr[j?+?1]]?=?[arr[j?+?1],?arr[j]];}}}return?arr;
}
8、vue-router vuex 等vue插件是怎么注入vue實例的?【描述】
9、vue-router 的 beforeEach 和 vue組件生命周期鉤子之間的執行順序【描述】
10、說一下vue響應式原理【描述】
Vue 響應式原理其實是在 vm._init() 中完成的,調用順序 initState() --> initData() --> observe() 。observe() 就是響應式的入口函數。
(1)observe(value):這個方法接收一個參數 value ,就是需要處理成響應式的對象;判斷 value 是否為對象,如果不是直接返回;判斷 value 對象是否有
__ob__
屬性,如果有直接返回;如果沒有,創建 observer 對象;返回 observer 對象;(2)Observer:給 value 對象定義不可枚舉的
__ob__
屬性,記錄當前的 observer 對象;數組的響應式處理,覆蓋原生的 push/splice/unshift 等方法,它們會改變原數組,當這些方法被調用時會發送通知;對象的響應式處理,調用 walk 方法,遍歷對象的每個屬性,調用 defineReactive ;(3)defineReactive:為每一個屬性創建 dep 對象,如果當前屬性的值是對象,再調用 observe ;定義 getter ,收集依賴,返回屬性的值;定義 setter ,保存新值,如果新值是對象,調用 observe,派發更新(發送通知),調用 dep.notify() ;
(4)依賴收集:在 Watcher 對象的 get 方法中調用 pushTarget 記錄 Dep.target 屬性;訪問 data 中的成員時收集依賴, defineReactive 的 getter 中收集依賴;把屬性對應的 watcher 對象添加到 dep 的 subs 數組中;給 childOb 收集依賴,目的是子對象添加和刪除成員時發送通知;
(5)Watcher:dep.notify 在調用 watcher 對象的 update() 方法時,調用 queueWatcher() ,判斷 watcher 是否被處理,如果沒有的話添加到 queue 隊列中,并調用 flushSchedulerQueue() : 觸發 beforeUpdate 鉤子,調用 watcher.run() , run() --> get() --> getter() --> updateComponent ,清空上一次的依賴,觸發 actived 鉤子,觸發 updated 鉤子。
11、vue的組件化是如何實現的【描述】一個 Vue 組件就是一個擁有預定義選項的一個 Vue 實例
一個組件可以組成頁面上一個功能完備的區域,組件可以包含腳本、樣式、模板
先創建父組件再創建子組件,先掛載子組件再掛載父組件
組件注冊方式:全局注冊和局部注冊
全局注冊,通過 Vue.component ,然后通過 Vue.extend 將組件配置轉換為組件的構造函數,記錄到 this.options.components.comp 里
(1)創建一個唯一值的cid ,目的是創建一個包裹著子構造函數通過原型繼承并且能夠緩存它們
(2)保存Vue構造函數,從緩存中加載組件的構造函數
(3)給 Sub 初始化一個 VueComponent 構造函數,內部調用 _init() 初始化
(4)Sub 原型繼承自 Vue ,然后cid自增并記錄到 Sub.cid ,合并 options
(5)初始化子組件的 props computed , 將 extend mixin use 等靜態方法繼承到 Sub
(6)把組件構造函數保存到 Ctor.options.components.comp = Ctor
(7)最后把組件的構造函數緩存到 options._Ctor ,返回 Sub
12、vuex 怎么使用,實現原理【描述】【舉例】
使用:
訪問 state : this.$store.state.count
訪問 getters : this.$store.getters.getCount
觸發 mutations : this.$store.commit('increate', 2)
觸發 actions : this.$store.dispatch('increateAsync', 5)
還有為了方便使用的 mapState mapGetters mapMutations mapActions
{computed:?{...mapState('cart',?'cartProducts')},methods:?{...mapMutations('cart',?'deleteFromCart')}
}
原理:
可以通過 Vue.use(Vuex) 注冊,所以要實現一個對象 Vuex,這個對象包含一個 install 方法
install 方法用于保存 Vue 構造函數,并往 Vue 原型上注冊 $store 屬性,
_Vue.prototype.$store = this.$options.store
然后實現一個 Vuex.Store 類,包含 state getters mutations actions 等屬性和方法
實現 state 屬性的關鍵是設置它為響應式數據,
this.state = _Vue.observable(state)
實現 getters 的關鍵是 遍歷用戶的 getters,為每一個 key 設置
Object.defineProperty
設置 get 方法然后分別定義 commit 和 dispatch 方法
13、Object.defineProperty 在實際業務中有什么應用?【舉例】
可以針對它的特性來說:
value: 設置屬性的值
writable: 值是否可以重寫。true | false
enumerable: 目標屬性是否可以被枚舉。true | false
configurable: 目標屬性是否可以被刪除或是否可以再次修改特性 true | false
getter 是一種獲得屬性值的方法
setter 是一種設置屬性值的方法
在特性中使用 get/set 屬性來定義對應的方法
注意:當使用了getter 或 setter 方法,不允許使用 writable 和 value 這兩個屬性
14、webpack的plugin是怎么實現的【描述】【舉例】
開發 Plugin 的思路:
plugin 是通過鉤子機制實現的,我們可以在不同的事件節點上掛載不同的任務,就可以擴展一個插件
插件必須是一個函數或者是一個包含 apply 方法的對象
一般可以把插件定義為一個類型,在類型中定義一個 apply 方法
apply 方法接收一個 compiler 參數,包含了這次構建的所有配置信息,通過這個對象注冊鉤子函數
通過 compiler.hooks.emit.tap 注冊鉤子函數(emit也可以為其他事件),鉤子函數第一個參數為插件名稱,第二個參數 compilation 為此次打包的上下文,根據 compilation.assets 就可以拿到此次打包的資源,做一些相應的邏輯處理
15、做的 nuxt 項目,是實時渲染還是后臺異步渲染【描述】
使用 asyncData 鉤子就是實時渲染16、nuxt應用性能問題瓶頸是什么,怎么優化【描述】【舉例】
主要性能問題:
Nuxt 服務端渲染應用最大的性能問題在于 Node 服務端渲染性能,模板轉換是 cpu 密集型的操作,node 又是單線程的,并發一高,cpu 就會飆到 100%。
客戶端的每次 request 都會到 node 服務器中,觸發后端渲染。渲染服務器引入 renderer 和相應的 vue 應用,根據 route 找到相應的組件和數據,拉組件再拉數據(可能是異步的),加載組件產生 DOM,然后再使用 renderToString 吐給 response 。
優化方法:
緩存(頁面緩存、組件緩存、API數據緩存)
服務器集群分布式(提高機器的處理數量)
控制好首屏模塊化個數,對返回的結果進行精簡,最小化,保證吐出到瀏覽器的內容足夠小。就是說并不要對所有模塊都做 SSR ,需要首屏呈現的/需要爬蟲爬的,就做直出,其他部分做 CSR 就行了
總結:
將 vue 渲染成 html 是 cpu 密集型的操作,node 又是單線程的,所以性能不是很好,想要提高并發,就得做緩存。
在 node 渲染服務器中做三層的緩存:頁面級別的緩存、組件級別的緩存、api 級別的緩存。由于搜索引擎的爬蟲不會攜帶用戶信息,還可以區分用戶登錄和非登錄的情況,針對非登錄用戶做服務端渲染 ssr ,對登錄用戶做客戶端渲染 spa。也不是所有頁面都需要服務端渲染,可以僅針對特定的路由做服務端渲染,還要控制首屏的大小,非必要的組件使用懶加載的方式在客戶端渲染,再加上多層的集群處理。
17、nuxt的渲染性能怎么去量化?有衡量過請求到后臺服務,后臺吐出來的時間嗎?【描述】
18、你們nuxt應用的服務器是什么?用的是自定義的node服務還是用nuxt自帶的服務?【描述】
19、最近在學什么技術?【描述】
20、你有什么問題想問我的?【描述】
最后
騰訊微保是騰訊旗下的一個保險平臺,算是騰訊子公司這樣,地點在松日鼎盛大廈。這家是剛開始面試,各方面準備不充足,部分問題沒答好,面試一輪游,不管怎樣,菜是原罪,繼續加油吧~
往期回顧:
三年經驗前端社招——眾安保險
三年經驗前端社招——有贊
三年經驗前端社招——Shopee
三年經驗前端社招——豐巢科技
三年經驗前端社招——樸樸科技
天生我材必有用,千金散盡還復來
最近組建了一個湖南人的前端交流群,如果你是湖南人可以加我微信?ruochuan12?私信 湖南?拉你進群。
推薦閱讀
1個月,200+人,一起讀了4周源碼
我讀源碼的經歷
老姚淺談:怎么學JavaScript?
我在阿里招前端,該怎么幫你(可進面試群)
·················?若川簡介?·················
你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列
從2014年起,每年都會寫一篇年度總結,已經寫了7篇,點擊查看年度總結。
同時,最近組織了源碼共讀活動,幫助1000+前端人學會看源碼。公眾號愿景:幫助5年內前端人走向前列。
識別上方二維碼加我微信、拉你進源碼共讀群
今日話題
略。歡迎分享、收藏、點贊、在看我的公眾號文章~